Data Exploration and Wrangling
The first step in performing any data analysis is to explore the data.
For example, we might want to better understand the variables included in the data, as we may learn about important details about the data that we should keep in mind as we try to predict our outcome variable.
First, let’s just get a general sense of our data. We can do that using the glimpse() function of the dplyr package (it is also in the tibble package).
We will also use the %>% pipe, which can be used to define the input for later sequential steps.
This will make more sense when we have multiple sequential steps using the same data object.
To use the pipe notation we need to install and load dplyr as well.
For example, here we start with pm data object and “pipe” the object into as input into the glimpse() function. The output is is an overview of what is in the pm object such as the number of rows and columns, all the column names, the data types for each column and the first view values in each column. The output below is scrollable so you can see everything from the glimpse() function.
Rows: 876
Columns: 50
$ id <dbl> 1003.001, 1027.000, 1033.100, 1049.100, 1…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.659091…
$ fips <dbl> 1003, 1027, 1033, 1049, 1055, 1069, 1073,…
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763, 3…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.9683…
$ state <chr> "Alabama", "Alabama", "Alabama", "Alabama…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb", "…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals", "…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772, 9…
$ zcta <dbl> 36532, 36251, 35660, 35962, 35901, 36303,…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 203836235…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, 90…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5.78…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.86764…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.23114…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.031646…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.973044…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 20126…
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 1015…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489, 5…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193, 9…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411, …
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626, …
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155, 8…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843, 9…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.21420…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894, 1…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.35366…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, 0.…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, 3.…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665, 4…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.000…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.350…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920, 4…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.330814…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.718…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2.7,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1, …
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37.2,…
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23.5,…
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, 17…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5, 7…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61.4,…
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333, 4…
We can see that there are 876 monitors (rows) and that we have 50 total variables (columns) - one of which is the outcome variable. In this case, the outcome variable is called value.
Notice that some of the variables that we would think of as factors (or categorical data) are currently of class character as indicated by the <chr> just to the right of the column names/variable names in the glimpse() output. This means that the variable values are character strings, such as words or phrases.
The other variables are of class <dbl>, which stands for double precision which indicates that the are numeric and that they have decimal values. In contrast, one could have integer values which would not allow for decimal numbers. Here is a link for more information on double precision numeric values.
Another common data class is factor which is abbreviated like this: <fct>. A factor is something that has unique levels but there is no appreciable order to the levels. For example we can have a numeric value that is just an id that we want to be interpreted as just a unique level and not as the number that it would typically indicate. This would be useful for several of our variables:
- the monitor ID (
id)
- the Federal Information Processing Standard number for the county where the monitor was located (
fips)
- the zip code tabulation area (
zcta)
None of the values actually have any real numeric meaning, so we want to make sure that R does not interpret them as if they do.
So let’s convert these variables into factors. We can do this using the across() function of the dplyr package and the as.factor() base function. The across() function has two main arguments: (i) the columns you want to operate on and (ii) the function or list of functions to apply to each column.
In this case, we are also using the magrittr assignment pipe or double pipe that looks like this %<>% of the magrittr package. This allows us use the pm data as input, but also reassigns the output to the same data object name.
Rows: 876
Columns: 50
$ id <fct> 1003.001, 1027.0001, 1033.1002, 1049.1003…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.659091…
$ fips <fct> 1003, 1027, 1033, 1049, 1055, 1069, 1073,…
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763, 3…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.9683…
$ state <chr> "Alabama", "Alabama", "Alabama", "Alabama…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb", "…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals", "…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772, 9…
$ zcta <fct> 36532, 36251, 35660, 35962, 35901, 36303,…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 203836235…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, 90…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5.78…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.86764…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.23114…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.031646…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.973044…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 20126…
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 1015…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489, 5…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193, 9…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411, …
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626, …
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155, 8…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843, 9…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.21420…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894, 1…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.35366…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, 0.…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, 3.…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665, 4…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.000…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.350…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920, 4…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.330814…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.718…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2.7,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1, …
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37.2,…
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23.5,…
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, 17…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5, 7…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61.4,…
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333, 4…
Great! Now we can see that these variables are now factors as indicated by <fct> after the variable name.
Skim package
The skim() function of the skimr package is also really helpful for getting a general sense of your data. By design, it provides summary statistics about variables in the data set.
Notice how there is a column called n_missing about the number of values that are missing.
This is also indicated by the complete_rate variable (or missing/number of observations).
In our data set, it looks like our data do not contain any missing data.
Also notice how the function provides separate tables of summary statistics for each data type: character, factor and numeric.
Next, the n_unqiue column shows us the number of unique values for each of our columns. We can see that there are 49 states represented in the data.
We can see that for many variables there are many low values as the distribution shows two peaks, one near zero and another with a higher value.
This is true for the imp variables (measures of development), the nei variables (measures of emission sources) and the road density variables.
We can also see that the range of some of the variables is very large, in particular the area and population related variables.
Let’s take a look to see which states are included using the distinct() function of the dplyr package:
Scroll through the output:
It looks like “District of Columbia” is being included as a state. We can see that Alaska and Hawaii are not included in the data.
Let’s also take a look to see how many monitors there are in a few cities. We can use the filter() function of the dplyr package to do so. For example, let’s look at Albuquerque, New Mexico.
# A tibble: 2 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 3500… 5.98 35001 35.1 -107. New … Berna… Albu… 10.1 87109 26199125
2 3500… 5.91 35001 35.1 -107. New … Berna… Albu… 10.1 87108 15224438
# … with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
We can see that there were only two monitors in the city of Albuquerque in 2006. Let’s compare this with Baltimore.
# A tibble: 5 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 2451… 12.2 24510 39.3 -76.6 Mary… Balti… Balt… 10.9 21251 461424
2 2451… 12.5 24510 39.3 -76.7 Mary… Balti… Balt… 10.9 21215 17645223
3 2451… 12.8 24510 39.3 -76.5 Mary… Balti… Balt… 10.9 21224 24539976
4 2451… 14.3 24510 39.2 -76.6 Mary… Balti… Balt… 10.9 21226 25718732
5 2451… 13.3 24510 39.3 -76.6 Mary… Balti… Balt… 10.9 21202 4111039
# … with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
There were in contrast five monitors for the city of Baltimore, despite the fact that if we take a look at the land area and population of the counties for Blatimore City and Albuquerque, we can see that they had very similar land area and populations.
# A tibble: 5 x 2
county_area county_pop
<dbl> <dbl>
1 209643241 620961
2 209643241 620961
3 209643241 620961
4 209643241 620961
5 209643241 620961
# A tibble: 2 x 2
county_area county_pop
<dbl> <dbl>
1 3006530549 662564
2 3006530549 662564
In fact, the county containing Albuerque had a larger population. Thus the measurements for Albuquerque were not as thorough as they were for Baltimore.
This may be due to the fact that the monitor values were lower in Albuquerque. It is interesting to note here that the CMAQ values are quite similar for both cities.
Evaluate correlation
In prediction analyses, it is also useful to evaluate if any of the variables are correlated. Why should we care about this?
If we are using a linear regression to model our data then we might run into a problem called multicolinearity which can lead us to misinterpret what is really predictive of our outcome variable. This phenomenon occurs when the predictor variables actually predict one another. See this case study for a deeper explanation about this.
Another reason we should look out for correlation is that we don’t want to include redundant variables. This can add unnecessary noise to our algorithm causing a reduction in prediction accuracy and it can cause our algorithm to be unnecessarily slower. Finally, it can also make it difficult to interpret what variables are actually predictive.
Intuitively we can expect some of our variables to be correlated.
Let’s first take a look at all of our numeric variables with thecorrplot package: The corrplot package is another option to look at correlation among possible predictors, and particularly useful if we have many predictors.
First, we calculate the Pearson correlation coefficients between all features pairwise using the cor() function of the stats package (which is loaded automatically). Then we use the corrplot::corrplot() function.
The tl.cex = 0.5 argument controls the size of the text label.
We can also plot the absolute value of the Pearson correlation coefficients using the abs() function from base R and change the order of the columns.

There are several options for ordering the variables. See here for more options. Here we will use the “hclust” option for ordering by hierarchical clustering - which will order the variables by how similar they are to one another.
The cl.lim = c(0, 1) argument limits the color label to be between 0 and 1.
We can see that the development variables (imp) variables are correlated with each other as we might expect. We also see that the road density variables seem to be correlated with each other, and the emission variables seem to be correlated with each other.
Also notice that none of the predictors are highly correlated with our outcome variable (value).
We can take also take a closer look using the ggcorr() function and the ggpairs() function of the GGally package.
To select our variables of interest we can use the select() function with the contains() function of the tidyr package.
First let’s look at the imp/development variables. We can change the default color palette (palette = "RdBu") and add on correlation coefficients to the plot (label = TRUE).


Indeed, we can see that imp_a1000 and imp_a500 are highly correlated, as well as imp_a10000, imp_a15000.
Next, let’s take a look at the road density data:

We can see that many of the road density variables are highly correlated with one another, while others are less so.
Finally let’s look at the emission variables.


We would also expect the population density data might correlate with some of these variables. Let’s take a look.


Interesting, so these variables don’t appear to be highly correlated, therefore we might need variables from each of the categories to predict our monitor PM2.5 pollution values.
Because some variables in our data have extreme values, it might be good to take a log transformation. This can affect our estimates of correlation.


Indeed this increased the correlation, but variables from each of these categories may still prove to be useful for prediction.
Now that we have a sense of what our data are, we can get started with building a machine learning model to predict air pollution.
Data Visualization
Our main question for this case study was:
Can we predict annual average air pollution concentrations at the granularity of zip code regional levels using predictors such as data about population density, urbanization, road density, as well as, satellite pollution data and chemical modeling data?
Thus far, we have build a machine learning (ML) model to predict fine particulate matter air pollution levels based on our predictor variables (or features).
Now, let’s make a plot of our predicted outcome values (\(\hat{Y}\)) and actual outcome values \(Y\) we observed.
First, let’s start by making a plot of our monitors. To do this, we will use the following packages to create a map of the US:
sf - the simple features package helps to convert geographical coordinates into geometry variables which are useful for making 2D plots
maps - this package contains geographical outlines and plotting functions to create plots with maps
rnaturalearth- this allows for easy interaction with map data from Natural Earth which is a public domain map dataset
rgeos - this package interfaces with the Geometry Engine-Open Source (GEOS) which is also helpful for coordinate conversion
We will start with getting an outline of the US with the ne_countries() function of the rnaturalearth package which will return polygons of the countries in the Natural Earth dataset.
Rows: 241
Columns: 64
$ scalerank <int> 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 3, 1, 5, 3, 1, 1, 1, 1, 1, 1…
$ featurecla <chr> "Admin-0 country", "Admin-0 country", "Admin-0 country", "…
$ labelrank <dbl> 5, 3, 3, 6, 6, 6, 6, 4, 2, 6, 4, 4, 5, 6, 6, 2, 4, 5, 6, 2…
$ sovereignt <chr> "Netherlands", "Afghanistan", "Angola", "United Kingdom", …
$ sov_a3 <chr> "NL1", "AFG", "AGO", "GB1", "ALB", "FI1", "AND", "ARE", "A…
$ adm0_dif <dbl> 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0…
$ level <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ type <chr> "Country", "Sovereign country", "Sovereign country", "Depe…
$ admin <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ adm0_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ geou_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ geounit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ gu_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ su_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ subunit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ su_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ brk_diff <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ name_long <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ brk_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ brk_name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ brk_group <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ abbrev <chr> "Aruba", "Afg.", "Ang.", "Ang.", "Alb.", "Aland", "And.", …
$ postal <chr> "AW", "AF", "AO", "AI", "AL", "AI", "AND", "AE", "AR", "AR…
$ formal_en <chr> "Aruba", "Islamic State of Afghanistan", "People's Republi…
$ formal_fr <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ note_adm0 <chr> "Neth.", NA, NA, "U.K.", NA, "Fin.", NA, NA, NA, NA, "U.S.…
$ note_brk <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Multiple clai…
$ name_sort <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ name_alt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ mapcolor7 <dbl> 4, 5, 3, 6, 1, 4, 1, 2, 3, 3, 4, 4, 1, 7, 2, 1, 3, 1, 2, 3…
$ mapcolor8 <dbl> 2, 6, 2, 6, 4, 1, 4, 1, 1, 1, 5, 5, 2, 5, 2, 2, 1, 6, 2, 2…
$ mapcolor9 <dbl> 2, 8, 6, 6, 1, 4, 1, 3, 3, 2, 1, 1, 2, 9, 5, 2, 3, 5, 5, 1…
$ mapcolor13 <dbl> 9, 7, 1, 3, 6, 6, 8, 3, 13, 10, 1, NA, 7, 11, 5, 7, 4, 8, …
$ pop_est <dbl> 103065, 28400000, 12799293, 14436, 3639453, 27153, 83888, …
$ gdp_md_est <dbl> 2258.0, 22270.0, 110300.0, 108.9, 21810.0, 1563.0, 3660.0,…
$ pop_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ lastcensus <dbl> 2010, 1979, 1970, NA, 2001, NA, 1989, 2010, 2010, 2001, 20…
$ gdp_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ economy <chr> "6. Developing region", "7. Least developed region", "7. L…
$ income_grp <chr> "2. High income: nonOECD", "5. Low income", "3. Upper midd…
$ wikipedia <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ fips_10 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ iso_a2 <chr> "AW", "AF", "AO", "AI", "AL", "AX", "AD", "AE", "AR", "AM"…
$ iso_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", "A…
$ iso_n3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", "0…
$ un_a3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", "0…
$ wb_a2 <chr> "AW", "AF", "AO", NA, "AL", NA, "AD", "AE", "AR", "AM", "A…
$ wb_a3 <chr> "ABW", "AFG", "AGO", NA, "ALB", NA, "ADO", "ARE", "ARG", "…
$ woe_id <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ adm0_a3_is <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", "A…
$ adm0_a3_us <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ adm0_a3_un <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ adm0_a3_wb <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ continent <chr> "North America", "Asia", "Africa", "North America", "Europ…
$ region_un <chr> "Americas", "Asia", "Africa", "Americas", "Europe", "Europ…
$ subregion <chr> "Caribbean", "Southern Asia", "Middle Africa", "Caribbean"…
$ region_wb <chr> "Latin America & Caribbean", "South Asia", "Sub-Saharan Af…
$ name_len <dbl> 5, 11, 6, 8, 7, 5, 7, 20, 9, 7, 14, 10, 23, 22, 17, 9, 7, …
$ long_len <dbl> 5, 11, 6, 8, 7, 13, 7, 20, 9, 7, 14, 10, 27, 35, 19, 9, 7,…
$ abbrev_len <dbl> 5, 4, 4, 4, 4, 5, 4, 6, 4, 4, 9, 4, 7, 10, 6, 4, 5, 4, 4, …
$ tiny <dbl> 4, NA, NA, NA, NA, 5, 5, NA, NA, NA, 3, NA, NA, 2, 4, NA, …
$ homepart <dbl> NA, 1, 1, NA, 1, NA, 1, 1, 1, 1, NA, 1, NA, NA, 1, 1, 1, 1…
$ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((-69.89912 1..., MULTIPOLYGON …
Here you can see the data about the countries in the world. Notice the geometry variable. This is used to create the outlines that we want.
Now we can use the geom_sf() function of the ggplot2 package to create a visual of simple feature (the geometry coordinates found in the geometry variable).

So now we can see that we have outlines of all the countries in the world.
We want to limit this just to the coordinates for the US. We will do this based on the coordinates we found on Wikipedia. According to this link, these are the latitude and longitude bounds of the continental US:
- top = 49.3457868 # north lat
- left = -124.7844079 # west long
- right = -66.9513812 # east long
- bottom = 24.7433195 # south lat
Now we just have a plot that is mostly limited to the outline of the US.
Now we will use the geom_point() function of the ggplot package to add scatter plot on top of the map. We want to show where the monitors are located based on the latitude and longitude values in the data.
Nice!
Now let’s add county lines.
County graphical data is available from the maps package. The sf package which again is short for simple features creates a data frame about this graphical data so that we can work with it.
Simple feature collection with 3076 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -124.6813 ymin: 25.12993 xmax: -67.00742 ymax: 49.38323
CRS: EPSG:4326
First 10 features:
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
7 alabama,butler MULTIPOLYGON (((-86.8604 31...
8 alabama,calhoun MULTIPOLYGON (((-85.74313 3...
9 alabama,chambers MULTIPOLYGON (((-85.59416 3...
10 alabama,cherokee MULTIPOLYGON (((-85.46812 3...
Now we will use this data within the geom_sf() function to add this to our plot. We will also add a title using the ggtitle() function, as well as remove axis ticks and titles using the theme() function of the ggplot2 package.
monitors <- ggplot(data = world) +
geom_sf(data = counties, fill = NA, color = gray(.5))+
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_point(data = pm, aes(x = lon, y = lat), size = 2,
shape = 23, fill = "darkred") +
ggtitle("Monitor Locations") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
monitors

Great!
Now, let’s add a fill at the county-level for the true monitor values of air pollution.
First, we need to get the county map data that we just got and our air pollution data to have similarly formatted county names so that we can combine the datasets together.
We can see that in the county data the counties are listed after the state name and a comma. In addition they are all lower case.
Simple feature collection with 6 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
CRS: EPSG:4326
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
In contrast, our air pollution pm data shows counties as titles with the first letter as upper case.
[1] "Baldwin" "Clay" "Colbert" "DeKalb" "Etowah" "Houston"
We can use the separate() function of the tidyr package to separate the ID variable of our counties data into two variables based on the comma as a separator.
Simple feature collection with 6 features and 2 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
CRS: EPSG:4326
state county geom
1 alabama autauga MULTIPOLYGON (((-86.50517 3...
2 alabama baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama barbour MULTIPOLYGON (((-85.42801 3...
4 alabama bibb MULTIPOLYGON (((-87.02083 3...
5 alabama blount MULTIPOLYGON (((-86.9578 33...
6 alabama bullock MULTIPOLYGON (((-85.66866 3...
Now we just need to make these names in the new county variable of the counties data to be in title format. We can use the str_to_title() function of the stringr package to do this.
Great! Now the county information is the same for the counties and pm data.
We can use the inner_join() function of the dplyr package to join the datasets together based on the county variables in each. This function will keep all rows that are in both datasets.
Rows: 3,926
Columns: 52
$ state.x <chr> "alabama", "alabama", "alabama", "alabama…
$ county <chr> "Baldwin", "Bibb", "Bibb", "Butler", "But…
$ id <fct> 1003.001, 13021.0007, 13021.0012, 39017.0…
$ value <dbl> 9.597647, 12.253134, 12.233673, 13.918079…
$ fips <fct> 1003, 13021, 13021, 39017, 39017, 13059, …
$ lat <dbl> 30.49800, 32.77746, 32.80541, 39.49380, 3…
$ lon <dbl> -87.88141, -83.64110, -83.54352, -84.3543…
$ state.y <chr> "Alabama", "Georgia", "Georgia", "Ohio", …
$ city <chr> "In a city", "In a city", "In a city", "I…
$ CMAQ <dbl> 8.098836, 11.716801, 11.716801, 11.321991…
$ zcta <fct> 36532, 31206, 31020, 45044, 45015, 30605,…
$ zcta_area <dbl> 190980522, 72325015, 276913325, 98746815,…
$ zcta_pop <dbl> 27829, 29072, 2541, 52822, 12038, 39952, …
$ imp_a500 <dbl> 0.01730104, 35.64359862, 0.28200692, 27.4…
$ imp_a1000 <dbl> 1.4096021, 24.4824827, 0.2973616, 28.2887…
$ imp_a5000 <dbl> 3.3360118, 8.7317283, 2.4691097, 22.69740…
$ imp_a10000 <dbl> 1.9879187, 9.1999720, 1.9873487, 11.90155…
$ imp_a15000 <dbl> 1.4386207, 6.4619966, 3.6435089, 8.405292…
$ county_area <dbl> 4117521611, 646879637, 646879637, 1209668…
$ county_pop <dbl> 182265, 155547, 155547, 368130, 368130, 1…
$ log_dist_to_prisec <dbl> 4.648181, 7.635438, 7.576493, 5.959728, 5…
$ log_pri_length_5000 <dbl> 8.517193, 10.215058, 10.659655, 9.747731,…
$ log_pri_length_10000 <dbl> 9.210340, 12.116408, 11.653566, 10.734382…
$ log_pri_length_15000 <dbl> 9.630228, 12.591833, 12.313347, 11.172817…
$ log_pri_length_25000 <dbl> 11.32735, 13.12475, 13.02383, 12.14238, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 6.214608, 8.104926, 7…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 7.600902, 9.180109, 8…
$ log_prisec_length_5000 <dbl> 10.81504, 11.61283, 11.34202, 11.63677, 1…
$ log_prisec_length_10000 <dbl> 11.88680, 13.23991, 12.47152, 12.62117, 1…
$ log_prisec_length_15000 <dbl> 12.20572, 13.74532, 13.37704, 13.26170, 1…
$ log_prisec_length_25000 <dbl> 13.41395, 14.28483, 14.25295, 14.16745, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.3180354, 5.5380414, 0.1972941, 7.230784…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967359, 5.538041, 5.536822, 7.408732, 5…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 5.986616, 5.986572, 7.538614, 7…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.3558851, 5.6035407, 0.9849611, 7.278576…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.2678341, 5.6035407, 5.5971561, 7.489928…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.6287284, 6.0302900, 6.0347672, 7.633004…
$ popdens_county <dbl> 44.265706, 240.457407, 240.457407, 304.32…
$ popdens_zcta <dbl> 145.716431, 401.963277, 9.176156, 534.923…
$ nohs <dbl> 3.300, 8.700, 6.800, 1.300, 3.500, 3.800,…
$ somehs <dbl> 4.900, 24.700, 17.500, 3.300, 7.700, 6.80…
$ hs <dbl> 25.10, 32.60, 46.60, 33.40, 33.40, 17.80,…
$ somecollege <dbl> 19.7, 12.9, 18.7, 23.0, 23.2, 16.1, 18.8,…
$ associate <dbl> 8.200, 4.800, 5.000, 8.700, 8.100, 5.100,…
$ bachelor <dbl> 25.30, 8.90, 4.00, 22.20, 16.20, 25.40, 5…
$ grad <dbl> 13.50, 7.30, 1.30, 8.10, 7.90, 25.00, 3.1…
$ pov <dbl> 6.100, 38.800, 26.800, 0.900, 6.900, 12.1…
$ hs_orless <dbl> 33.30, 66.00, 70.90, 38.00, 44.60, 28.40,…
$ urc2013 <dbl> 4, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, 4,…
$ urc2006 <dbl> 5, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, 4,…
$ aod <dbl> 37.36364, 36.25000, 30.45455, 48.36364, 5…
$ geom <MULTIPOLYGON [°]> MULTIPOLYGON (((-87.93757 3.…
Nice! we can see that we have add a geom variable to the pm data.
Now we can use this to color the counties in our plot based on the value variable of our pm data, which you may recall is the actual monitor data for fine particulate air pollution at each monitor.
WE can do so using the scale_fill_gradientn() function of the ggplot2 package which creates color gradient based on a variable. In this case it is the variable that was specified as the fill in the aes function of the geom_sf() function. We specified that it would be the value variable of the pm data.
This scale_fill_gradientn() function also allows you to specify the colors, what to do about NA values (should they be a specific color or transparent) and the breaks, limits, labels and name/title on the legend for the color gradient.
truth <-ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50), expand = FALSE)+
geom_sf(data = map_data, aes(fill = value)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("True PM 2.5 levels") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
truth
Nice!
Now let’s do the same with our predicted outcome values.
Let’s grab both the testing and training predicted outcome values so that we have as much data as possible.
First we need to fit our training data with our final model to be able to get the predictions for the monitors included in the training set. We did this using the last_fit() function, but the output of this makes it difficult to grab the predicted values for the training data, and it is also difficult to get the id variables for the testing data.
Thus we will use the parsnip fit() and predict() functions of the parsnip package to do this like so:
Question Opportunity
Why do we not need pre-processed data?
Click here to reveal the answer.
Since we are using a workflow, the data will be pre-processed when it is fit as well.
# A tibble: 584 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 10.0 9.60 1003 Baldwin 1003.001
2 11.0 10.8 1027 Clay 1027.0001
3 11.5 11.2 1033 Colbert 1033.1002
4 12.0 12.4 1055 Etowah 1055.001
5 10.8 10.5 1069 Houston 1069.0003
6 14.5 15.6 1073 Jefferson 1073.0023
7 12.1 12.4 1073 Jefferson 1073.1005
8 11.0 11.1 1073 Jefferson 1073.1009
9 13.9 14.6 1073 Jefferson 1073.2003
10 11.8 12.0 1073 Jefferson 1073.5002
# … with 574 more rows
# A tibble: 292 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.7 11.7 1049 DeKalb 1049.1003
2 12.6 13.1 1073 Jefferson 1073.101
3 12.3 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.5 11.4 1103 Morgan 1103.0011
6 12.4 12.2 1121 Talladega 1121.0002
7 10.8 10.9 4013 Maricopa 4013.4003
8 10.4 10.6 4021 Pinal 4021.0001
9 12.0 14.1 4023 Santa Cruz 4023.0004
10 7.69 5.83 4025 Yavapai 4025.2002
# … with 282 more rows
Now we can combine this data for the predictions for all monitors using the bind_rows() function of the dplyr package, which will essentially append the second dataset to the first.
# A tibble: 876 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.7 11.7 1049 DeKalb 1049.1003
2 12.6 13.1 1073 Jefferson 1073.101
3 12.3 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.5 11.4 1103 Morgan 1103.0011
6 12.4 12.2 1121 Talladega 1121.0002
7 10.8 10.9 4013 Maricopa 4013.4003
8 10.4 10.6 4021 Pinal 4021.0001
9 12.0 14.1 4023 Santa Cruz 4023.0004
10 7.69 5.83 4025 Yavapai 4025.2002
# … with 866 more rows
Great! as we can see there are 876 values like we would expect for all of the monitors. We can use the county variable to combine this with the counties data like we did with the pm data previously so that we can use the value variable as a color scheme for our map.
map_data <- inner_join(counties, all_pred, by = "county")
pred <- ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_sf(data = map_data, aes(fill = .pred)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("Predicted PM 2.5 levels")+
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
pred

Now we will use the patchwork package to combine our last two plots. This allows us to combine plots using the + or the / . The + will place plots side by side and the / will place plots top to bottom.
Now let’s just combine the truth plot and the prediction plots together:

We can see that the predicted fine particle air pollution values in (ug/m3) are quite similar to the true values measured by the actual gravimetric monitors. We can also see that southern California has some large counties with worse pollution (as they are yellow and thus have much higher particulate matter levels).
Let’s add some text to our plot to explain it a bit more. We can do so using the plot_annotation() function of the patchwork package. The theme argument of this function takes the same theme information using the theme() function of the ggplot2 package as when creating ggplot2plots.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXM6IFByZWRpY3RpbmcgQW5udWFsIEFpciBQb2xsdXRpb24iCmNzczogc3R5bGUuY3NzCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgc2VsZl9jb250YWluZWQ6IHllcwogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vCiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogeWVzCgotLS0KPHN0eWxlPgojVE9DIHsKICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9pbWcvbG9nby5qcGciKTsKICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47CiAgcGFkZGluZy10b3A6IDI0MHB4ICFpbXBvcnRhbnQ7CiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsKfQo8L3N0eWxlPgoKPCEtLSBPcGVuIGFsbCBsaW5rcyBpbiBuZXcgdGFiLS0+ICAKPGJhc2UgdGFyZ2V0PSJfYmxhbmsiLz4gCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKbGlicmFyeShoZXJlKQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAnOTAlJykKYGBgCgoKIyMjIyB7Lm91dGxpbmUgfQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5fcGxvdF9tYXBzLnBuZyIpKQpgYGAKCiMjIyMKCiMjIyMgey5kaXNjbGFpbWVyX2Jsb2NrfQoKKipEaXNjbGFpbWVyKio6IFRoZSBwdXJwb3NlIG9mIHRoZSBbT3BlbiBDYXNlIFN0dWRpZXNdKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pbyl7dGFyZ2V0PSJfYmxhbmsifSBwcm9qZWN0IGlzICoqdG8gZGVtb25zdHJhdGUgdGhlIHVzZSBvZiB2YXJpb3VzIGRhdGEgc2NpZW5jZSBtZXRob2RzLCB0b29scywgYW5kIHNvZnR3YXJlIGluIHRoZSBjb250ZXh0IG9mIG1lc3N5LCByZWFsLXdvcmxkIGRhdGEqKi4gQSBnaXZlbiBjYXNlIHN0dWR5IGRvZXMgbm90IGNvdmVyIGFsbCBhc3BlY3RzIG9mIHRoZSByZXNlYXJjaCBwcm9jZXNzLCBpcyBub3QgY2xhaW1pbmcgdG8gYmUgdGhlIG1vc3QgYXBwcm9wcmlhdGUgd2F5IHRvIGFuYWx5emUgYSBnaXZlbiBkYXRhIHNldCwgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBpbiB0aGUgY29udGV4dCBvZiBtYWtpbmcgcG9saWN5IGRlY2lzaW9ucyB3aXRob3V0IGV4dGVybmFsIGNvbnN1bHRhdGlvbiBmcm9tIHNjaWVudGlmaWMgZXhwZXJ0cy4gCgojIyMjCgojIyMjIHsubGljZW5zZV9ibG9ja30KClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBbKENDIEJZLU5DIDMuMCldKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvdXMvKXt0YXJnZXQ9Il9ibGFuayJ9IFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4KCiMjIyMKCiMjIyMgey5yZWZlcmVuY2VfYmxvY2t9CgpUbyBjaXRlIHRoaXMgY2FzZSBzdHVkeSBwbGVhc2UgdXNlOgoKV3JpZ2h0LCBDYXJyaWUgYW5kIEphZ2VyLCBMZWFoIGFuZCBUYXViLCBNYXJnYXJldCBhbmQgSGlja3MsIFN0ZXBoYW5pZS4gKDIwMjApLiBbaHR0cHM6Ly93d3cub3BlbmNhc2VzdHVkaWVzLm9yZy9vY3MtYnAtYWlyLXBvbGx1dGlvbi9dKGh0dHBzOi8vd3d3Lm9wZW5jYXNlc3R1ZGllcy5vcmcvb2NzLWJwLWFpci1wb2xsdXRpb24vKS4gUHJlZGljdGluZyBBbm51YWwgQWlyIFBvbGx1dGlvbiAoVmVyc2lvbiB2MS4wLjApLgoKIyMjIwoKIyAqKk1vdGl2YXRpb24qKgoqKioKQSB2YXJpZXR5IG9mIGRpZmZlcmVudCBzb3VyY2VzIGNvbnRyaWJ1dGUgZGlmZmVyZW50IHR5cGVzIG9mIHBvbGx1dGFudHMgdG8gd2hhdCB3ZSBjYWxsIGFpciBwb2xsdXRpb24uIAoKU29tZSBzb3VyY2VzIGFyZSBuYXR1cmFsIHdoaWxlIG90aGVycyBhcmUgYW50aHJvcG9nZW5pYyAoaHVtYW4gZGVyaXZlZCk6Cgo8cCBhbGlnbj0iY2VudGVyIj4KPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vd3d3Lm5wcy5nb3Yvc3ViamVjdHMvYWlyL2ltYWdlcy9Tb3VyY2VzX0dyYXBoaWNfSHVnZS5qcGc/bWF4d2lkdGg9MTIwMCZtYXhoZWlnaHQ9MTIwMCZhdXRvcm90YXRlPWZhbHNlIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5nb29nbGUuY29tL3VybD9zYT1pJnVybD1odHRwcyUzQSUyRiUyRnd3dy5ucHMuZ292JTJGc3ViamVjdHMlMkZhaXIlMkZzb3VyY2VzLmh0bSZwc2lnPUFPdlZhdzJ2N0FWeFNGOFpTQVBFaE51ZFZ0Yk4mdXN0PTE1ODU3NzA5NjYyMTcwMDAmc291cmNlPWltYWdlcyZjZD12ZmUmdmVkPTBDQUlRalJ4cUZ3b1RDUERONjZxX3hlZ0NGUUFBQUFBZEFBQUFBQkFEKXt0YXJnZXQ9Il9ibGFuayJ9CgojIyMgTWFqb3IgdHlwZXMgb2YgYWlyIHBvbGx1dGFudHMKCjEpICoqR2FzZW91cyoqIC0gQ2FyYm9uIE1vbm94aWRlIChDTyksIE96b25lIChPfjN+KSwgTml0cm9nZW4gT3hpZGVzKE5PLCBOT34yfiksIFN1bHBoZXIgRGlveGlkZSAoU09+Mn4pCjIpICoqUGFydGljdWxhdGUqKiAtIHNtYWxsIGxpcXVpZHMgYW5kIHNvbGlkcyBzdXNwZW5kZWQgaW4gdGhlIGFpciAoaW5jbHVkZXMgbGVhZC0gY2FuIGluY2x1ZGUgY2VydGFpbiB0eXBlcyBvZiBkdXN0KQozKSAqKkR1c3QqKiAtIHNtYWxsIHNvbGlkcyAobGFyZ2VyIHRoYW4gcGFydGljdWxhdGVzKSB0aGF0IGNhbiBiZSBzdXNwZW5kZWQgaW4gdGhlIGFpciBmb3Igc29tZSB0aW1lIGJ1dCBldmVudHVhbGx5IHNldHRsZQo0KSAqKkJpb2xvZ2ljYWwqKiAtIHBvbGxlbiwgYmFjdGVyaWEsIHZpcnVzZXMsIG1vbGQgc3BvcmVzCgpTZWUgW2hlcmVdKGh0dHA6Ly93d3cucmVkbG9nZW52LmNvbS93b3JrZXItc2FmZXR5L3BhcnQtMS1kdXN0LWFuZC1wYXJ0aWN1bGF0ZS1tYXR0ZXIpIGZvciBtb3JlIGRldGFpbCBvbiB0aGUgdHlwZXMgb2YgcG9sbHV0YW50cyBpbiB0aGUgYWlyLgoKCiMjIyBQYXJ0aWN1bGF0ZSBwb2xsdXRpb24gCgpBaXIgcG9sbHV0aW9uIHBhcnRpY3VsYXRlcyBhcmUgZ2VuZXJhbGx5IGRlc2NyaWJlZCBieSB0aGVpciAqKnNpemUqKi4KClRoZXJlIGFyZSAzIG1ham9yIGNhdGVnb3JpZXM6CgoxKSAqKkxhcmdlIENvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAtIGhhcyBkaWFtZXRlciBvZiA+MTAgbWljcm9tZXRlcnMgKDEwIMK1bSkgCgoyKSAqKkNvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAoY2FsbGVkICoqUE1+MTAtMi41fioqKSAtIGhhcyBkaWFtZXRlciBvZiBiZXR3ZWVuIDIuNSDCtW0gYW5kIDEwIMK1bQoKMykgKipGaW5lKiogUGFydGljdWxhdGUgTWF0dGVyIChjYWxsZWQgKipQTX4yLjV+KiopIC0gaGFzIGRpYW1ldGVyIG9mIDwgMi41IMK1bSAKCioqUE1+MTB+KiogaW5jbHVkZXMgYW55IHBhcnRpY3VsYXRlIG1hdHRlciA8MTAgwrVtIChib3RoIGNvYXJzZSBhbmQgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIpCgpIZXJlIHlvdSBjYW4gc2VlIGhvdyB0aGVzZSBzaXplcyBjb21wYXJlIHdpdGggYSBodW1hbiBoYWlyOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiNjAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInBtMi41X3NjYWxlX2dyYXBoaWMtY29sb3JfMi5qcGciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmVwYS5nb3YvcG0tcG9sbHV0aW9uL3BhcnRpY3VsYXRlLW1hdHRlci1wbS1iYXNpY3Mpe3RhcmdldD0iX2JsYW5rIn0KCjwhLS0gPHAgYWxpZ249ImNlbnRlciI+IC0tPgo8IS0tICAgPGltZyB3aWR0aD0iNTAwIiBzcmM9Imh0dHBzOi8vd3d3LnNlbnNpcmlvbi5jb20vaW1hZ2VzL3NlbnNpcmlvbi1zcGVjaWFsaXN0LWFydGljbGUtZmlndXJlLTEtY2RkNzAuanBnIj4gLS0+CjwhLS0gPC9wPiAtLT4KCgo8dT5UaGUgZm9sbG93aW5nIHBsb3QgYW5kIHRhYmxlIHNob3cgdGhlIHJlbGF0aXZlIHNpemVzIG9mIHRoZXNlIGRpZmZlcmVudCBwb2xsdXRhbnRzIGluIG1pY3JvbWV0ZXJzICjCtW0pOjwvdT4KCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjYwMCIgc3JjPSJodHRwczovL3VwbG9hZC53aWtpbWVkaWEub3JnL3dpa2lwZWRpYS9jb21tb25zL3RodW1iL2QvZGYvQWlyYm9ybmUtcGFydGljdWxhdGUtc2l6ZS1jaGFydC5zdmcvODAwcHgtQWlyYm9ybmUtcGFydGljdWxhdGUtc2l6ZS1jaGFydC5zdmcucG5nIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QYXJ0aWN1bGF0ZXMpe3RhcmdldD0iX2JsYW5rIn0KCgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI1MDAiIHNyYz0iaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2ZpbGVzL0FydGljbGVzLzUwNTU3MC9mcHViaC0wOC0wMDAxNC1IVE1ML2ltYWdlX20vZnB1YmgtMDgtMDAwMTQtdDAwMi5qcGciPgo8L3A+CgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmZyb250aWVyc2luLm9yZy9hcnRpY2xlcy8xMC4zMzg5L2ZwdWJoLjIwMjAuMDAwMTQvZnVsbCl7dGFyZ2V0PSJfYmxhbmsifQoKCjx1PlRoaXMgdGFibGUgc2hvd3MgaG93IGRlZXBseSBzb21lIG9mIHRoZSBzbWFsbGVyIGZpbmUgcGFydGljbGVzIGNhbiBwZW5ldHJhdGUgd2l0aGluIHRoZSBodW1hbiBib2R5OjwvdT4KCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjUwMCIgc3JjPSJodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvZmlsZXMvQXJ0aWNsZXMvNTA1NTcwL2ZwdWJoLTA4LTAwMDE0LUhUTUwvaW1hZ2VfbS9mcHViaC0wOC0wMDAxNC10MDAxLmpwZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnB1YmguMjAyMC4wMDAxNC9mdWxsKXt0YXJnZXQ9Il9ibGFuayJ9CgoKIyMjIE5lZ2F0aXZlIGltcGFjdCBvZiBwYXJ0aWN1bGF0ZSBleHBvc3VyZSBvbiBoZWFsdGggCgpFeHBvc3VyZSB0byBhaXIgcG9sbHV0aW9uIGlzIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgcmF0ZXMgb2YgW21vcnRhbGl0eV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNTc4MzE4Ni8pe3RhcmdldD0iX2JsYW5rIn0gaW4gb2xkZXIgYWR1bHRzIGFuZCBpcyBrbm93biB0byBiZSBhIHJpc2sgZmFjdG9yIGZvciBtYW55IGRpc2Vhc2VzIGFuZCBjb25kaXRpb25zIGluY2x1ZGluZyBidXQgbm90IGxpbWl0ZWQgdG86CgoxKSBbQXN0aG1hXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8yOTI0MzkzNyl7dGFyZ2V0PSJfYmxhbmsifSAtIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKCoqUE1+Mi41fioqKSB3YXMgZm91bmQgdG8gYmUgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciByYXRlcyBvZiBhc3RobWEgaW4gY2hpbGRyZW4KMikgW0luZmxhbW1hdGlvbiBpbiB0eXBlIDEgZGlhYmV0ZXNdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzMxNDE5NzY1KXt0YXJnZXQ9Il9ibGFuayJ9IC0gZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAoKipQTX4yLjV+KiopIGZyb20gdHJhZmZpYy1yZWxhdGVkIGFpciBwb2xsdXRpb24gd2FzIGFzc29jaWF0ZWQgd2l0aCBpbmNyZWFzZWQgbWVhc3VyZXMgb2YgaW5mbGFtbWF0b3J5IG1hcmtlcnMgaW4geW91dGhzIHdpdGggVHlwZSAxIGRpYWJldGVzCjMpIFtMdW5nIGZ1bmN0aW9uIGFuZCBlbXBoeXNlbWFdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzMxNDA4MTM1KXt0YXJnZXQ9Il9ibGFuayJ9IC0gaGlnaGVyIGNvbmNlbnRyYXRpb25zIG9mIG96b25lIChPfjN+KSwgbml0cm9nZW4gb3hpZGVzIChOT354fiksIGJsYWNrIGNhcmJvbiwgYW5kIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKipQTX4yLjV+KiogLCBhdCBzdHVkeSBiYXNlbGluZSB3ZXJlIHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGdyZWF0ZXIgaW5jcmVhc2VzIGluIHBlcmNlbnQgZW1waHlzZW1hIHBlciAxMCB5ZWFycyAKNCkgW0xvdyBiaXJ0aHdlaWdodF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzEzODY2NDMpe3RhcmdldD0iX2JsYW5rIn0gLSBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlKCoqUE1+Mi41fioqKSB3YXMgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIGJpcnRoIHdlaWdodCBpbiBmdWxsLXRlcm0gbGl2ZSBiaXJ0aHMKNSkgW1ZpcmFsIEluZmVjdGlvbl0oaHR0cHM6Ly93d3cudGFuZGZvbmxpbmUuY29tL2RvaS9mdWxsLzEwLjEwODAvMDg5NTgzNzA3MDE2NjU0MzQpe3RhcmdldD0iX2JsYW5rIn0gLSBoaWdoZXIgcmF0ZXMgb2YgaW5mZWN0aW9uIGFuZCBpbmNyZWFzZWQgc2V2ZXJpdHkgb2YgaW5mZWN0aW9uIGFyZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIGV4cG9zdXJlcyB0byBwb2xsdXRpb24gbGV2ZWxzIGluY2x1ZGluZyBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlICgqKlBNfjIuNX4qKikKClNlZSB0aGlzIFtyZXZpZXcgYXJ0aWNsZV0oaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnB1YmguMjAyMC4wMDAxNC9mdWxsKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHNvdXJjZXMgb2YgYWlyIHBvbGx1dGlvbiBhbmQgdGhlIGluZmx1ZW5jZSBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aC4KCiMjIyBTcGFyc2UgbW9uaXRvcmluZyBpcyBwcm9ibGVtYXRpYyBmb3IgUHVibGljIEhlYWx0aAoKSGlzdG9yaWNhbGx5LCBlcGlkZW1pb2xvZ2ljYWwgc3R1ZGllcyB3b3VsZCBhc3Nlc3MgdGhlIGluZmx1ZW5jZSBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aCBvdXRjb21lcyBieSByZWx5aW5nIG9uIGEgbnVtYmVyIG9mIG1vbml0b3JzIGxvY2F0ZWQgYXJvdW5kIHRoZSBjb3VudHJ5LiAKCkhvd2V2ZXIsIGFzIGNhbiBiZSBzZWVuIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlLCB0aGVzZSBtb25pdG9ycyBhcmUgcmVsYXRpdmVseSBzcGFyc2UgaW4gY2VydGFpbiByZWdpb25zIG9mIHRoZSBjb3VudHJ5IGFuZCBhcmUgbm90IG5lY2Vzc2FyaWx5IGxvY2F0ZWQgbmVhciBwb2xsdXRpb24gc291cmNlcy4gV2Ugd2lsbCBzZWUgbGF0ZXIgd2hlbiB3ZSBldmFsdWF0ZSB0aGUgZGF0YSwgdGhhdCBldmVuIGluIGNlcnRhaW4gcmVsYXRpdmVseSBsYXJnZSBjaXRpZXMgdGhlcmUgaXMgb25seSAgb25lIG1vbml0b3IhCgpGdXJ0aGVybW9yZSwgZHJhbWF0aWMgZGlmZmVyZW5jZXMgaW4gcG9sbHV0aW9uIHJhdGVzIGNhbiBiZSBzZWVuIGV2ZW4gd2l0aGluIHRoZSBzYW1lIGNpdHkuIEluIGZhY3QsIHRoZSB0ZXJtIG1pY3JvLWVudmlyb25tZW50cyBkZXNjcmliZXMgZW52aXJvbm1lbnQgd2l0aGluIGNpdGllcyBvciBjb3VudGllcyB3aGljaCBtYXkgdmFyeSBncmVhdGx5IGZyb20gb25lIGJsb2NrIHRvIGFub3RoZXIuCgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI0MDAiIHNyYz0iaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNDEzNzI3Mi9iaW4vMTQ3Ni0wNjlYLTEzLTYzLTEuanBnIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2Voam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzYtMDY5WC0xMy02Myl7dGFyZ2V0PSJfYmxhbmsifQoKVGhpcyBsYWNrIG9mIGdyYW51bGFyaXR5IGluIGFpciBwb2xsdXRpb24gbW9uaXRvcmluZyBoYXMgaGluZGVyZWQgb3VyIGFiaWxpdHkgdG8gZGlzY2VybiB0aGUgZnVsbCBpbXBhY3Qgb2YgYWlyIHBvbGx1dGlvbiBvbiBoZWFsdGggYW5kIHRvIGlkZW50aWZ5IGF0LXJpc2sgbG9jYXRpb25zLiAKCgojIyMgTWFjaGluZSBsZWFybmluZyBvZmZlcnMgYSBzb2x1dGlvbgoKQW4gW2FydGljbGVdKGh0dHBzOi8vZWhqb3VybmFsLmJpb21lZGNlbnRyYWwuY29tL2FydGljbGVzLzEwLjExODYvMTQ3Ni0wNjlYLTEzLTYzKXt0YXJnZXQ9Il9ibGFuayJ9IHB1Ymxpc2hlZCBpbiB0aGUgKkVudmlyb25tZW50YWwgSGVhbHRoKiBqb3VybmFsIGRlYWx0IHdpdGggdGhpcyBpc3N1ZSBieSB1c2luZyBkYXRhLCBpbmNsdWRpbmcgcG9wdWxhdGlvbiBkZW5zaXR5LCByb2FkIGRlbnNpdHksIGFtb25nIG90aGVyIGZlYXR1cmVzLCB0byBtb2RlbCBvciBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIGF0IGEgbW9yZSBsb2NhbGl6ZWQgc2NhbGUgdXNpbmcgbWFjaGluZSBsZWFybmluZyAoTUwpIG1ldGhvZHMuIAoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInRoZXBhcGVyLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oc291cmNlaHR0cHM6Ly9laGpvdXJuYWwuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni8xNDc2LTA2OVgtMTMtNjMpCgojIyMjIHsucmVmZXJlbmNlX2Jsb2NrfQpZYW5vc2t5LCBKLiBELiBldCBhbC4gU3BhdGlvLXRlbXBvcmFsIG1vZGVsaW5nIG9mIHBhcnRpY3VsYXRlIGFpciBwb2xsdXRpb24gaW4gdGhlIGNvbnRlcm1pbm91cyBVbml0ZWQgU3RhdGVzIHVzaW5nIGdlb2dyYXBoaWMgYW5kIG1ldGVvcm9sb2dpY2FsIHByZWRpY3RvcnMuICpFbnZpcm9uIEhlYWx0aCogMTMsIDYzICgyMDE0KS4KCiMjIyMKClRoZSBhdXRob3JzIG9mIHRoaXMgYXJ0aWNsZSBzdGF0ZSB0aGF0OgoKPiAiRXhwb3N1cmUgdG8gYXRtb3NwaGVyaWMgcGFydGljdWxhdGUgbWF0dGVyIChQTSkgcmVtYWlucyBhbiBpbXBvcnRhbnQgcHVibGljIGhlYWx0aCBjb25jZXJuLCBhbHRob3VnaCBpdCByZW1haW5zIGRpZmZpY3VsdCB0byBxdWFudGlmeSBhY2N1cmF0ZWx5IGFjcm9zcyBsYXJnZSBnZW9ncmFwaGljIGFyZWFzIHdpdGggc3VmZmljaWVudGx5IGhpZ2ggc3BhdGlhbCByZXNvbHV0aW9uLiBSZWNlbnQgZXBpZGVtaW9sb2dpYyBhbmFseXNlcyBoYXZlIGRlbW9uc3RyYXRlZCB0aGUgaW1wb3J0YW5jZSBvZiBzcGF0aWFsbHktIGFuZCB0ZW1wb3JhbGx5LXJlc29sdmVkIGV4cG9zdXJlIGVzdGltYXRlcywgd2hpY2ggc2hvdyBsYXJnZXIgUE0tbWVkaWF0ZWQgaGVhbHRoIGVmZmVjdHMgYXMgY29tcGFyZWQgdG8gbmVhcmVzdCBtb25pdG9yIG9yIGNvdW50eS1zcGVjaWZpYyBhbWJpZW50IGNvbmNlbnRyYXRpb25zLiIgCgoKClRoZSBhcnRpY2xlIGFib3ZlIGRlbW9uc3RyYXRlcyB0aGF0IG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyBjYW4gYmUgdXNlZCB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIHdoZW4gdHJhZGl0aW9uYWwgbW9uaXRvcmluZyBzeXN0ZW1zIGFyZSBub3QgYXZhaWxhYmxlIGluIGEgcGFydGljdWxhciBhcmVhIG9yIHdoZW4gdGhlcmUgaXMgbm90IGVub3VnaCBzcGF0aWFsIGdyYW51bGFyaXR5IHdpdGggY3VycmVudCBtb25pdG9yaW5nIHN5c3RlbXMuIApXZSB3aWxsIHVzZSBzaW1pbGFyIG1ldGhvZHMgdG8gcHJlZGljdCBhbm51YWwgYWlyIHBvbGx1dGlvbiBsZXZlbHMgc3BhdGlhbGx5IHdpdGhpbiB0aGUgVVMuCgoKIyAqKk1haW4gUXVlc3Rpb24qKgoqKioKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb246IDwvdT48L2I+CgoxKSBDYW4gd2UgcHJlZGljdCBhbm51YWwgYXZlcmFnZSBhaXIgcG9sbHV0aW9uIGNvbmNlbnRyYXRpb25zIGF0IHRoZSBncmFudWxhcml0eSBvZiB6aXAgY29kZSByZWdpb25hbCBsZXZlbHMgdXNpbmcgcHJlZGljdG9ycyBzdWNoIGFzIGRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5LCB1cmJhbml6YXRpb24sIHJvYWQgZGVuc2l0eSwgYXMgd2VsbCBhcywgc2F0ZWxsaXRlIHBvbGx1dGlvbiBkYXRhIGFuZCBjaGVtaWNhbCBtb2RlbGluZyBkYXRhPwoKIyMjIwoKIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKgoqKioKCkluIHRoaXMgY2FzZSBzdHVkeSwgd2Ugd2lsbCB3YWxrIHlvdSB0aHJvdWdoIGltcG9ydGluZyBkYXRhIGZyb20gQ1NWIGZpbGVzIGFuZCBwZXJmb3JtaW5nIG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyB0byBwcmVkaWN0IG91ciBvdXRjb21lIHZhcmlhYmxlIG9mIGludGVyZXN0IChpbiB0aGlzIGNhc2UgYW5udWFsIGZpbmUgcGFydGljbGUgYWlyIHBvbGx1dGlvbiBlc3RpbWF0ZXMpLiAKCldlIHdpbGwgZXNwZWNpYWxseSBmb2N1cyBvbiB1c2luZyBwYWNrYWdlcyBhbmQgZnVuY3Rpb25zIGZyb20gdGhlIFtgdGlkeXZlcnNlYF0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0sIGFuZCBtb3JlIHNwZWNpZmljYWxseSB0aGUgW2B0aWR5bW9kZWxzYF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3RpZHltb2RlbHMvdGlkeW1vZGVscy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gcGFja2FnZS9lY29zeXN0ZW0gcHJpbWFyaWx5IGRldmVsb3BlZCBhbmQgbWFpbnRhaW5lZCBieSBbTWF4IEt1aG5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvbWF4LWt1aG4pe3RhcmdldD0iX2JsYW5rIn0gYW5kIFtEYXZpcyBWYXVnaGFuXShodHRwczovL3Jlc291cmNlcy5yc3R1ZGlvLmNvbS9hdXRob3JzL2RhdmlzLXZhdWdoYW4pe3RhcmdldD0iX2JsYW5rIn0uIApUaGlzIHBhY2thZ2UgbG9hZHMgbW9yZSBtb2RlbGluZyByZWxhdGVkIHBhY2thZ2VzIGxpa2UgYHJzYW1wbGVgLCBgcmVjaXBlc2AsIGBwYXJzbmlwYCwgYHlhcmRzdGlja2AsIGB3b3JrZmxvd3NgLCBhbmQgYHR1bmVgIHBhY2thZ2VzLiAKClRoZSB0aWR5dmVyc2UgaXMgYSBsaWJyYXJ5IG9mIHBhY2thZ2VzIGNyZWF0ZWQgYnkgUlN0dWRpby4gCldoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGxlZ2libGUgYW5kIGludHVpdGl2ZS4KCgpgYGB7ciwgb3V0LndpZHRoID0gIjIwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKVGhlIHNraWxscywgbWV0aG9kcywgYW5kIGNvbmNlcHRzIHRoYXQgc3R1ZGVudHMgd2lsbCBiZSBmYW1pbGlhciB3aXRoIGJ5IHRoZSBlbmQgb2YgdGhpcyBjYXNlIHN0dWR5IGFyZToKCgo8dT4qKkRhdGEgU2NpZW5jZSBMZWFybmluZyBPYmplY3RpdmVzOioqPC91PiAKICAKMS4gRmFtaWxpYXJpdHkgd2l0aCB0aGUgdGlkeW1vZGVscyBlY29zeXN0ZW0KMi4gQWJpbGl0eSB0byBldmFsdWF0ZSBjb3JyZWxhdGlvbiBhbW9uZyBwcmVkaWN0b3IgdmFyaWFibGVzIChgY29ycnBsb3RgIGFuZCBgR0dhbGx5YCkKMy4gQWJpbGl0eSB0byBpbXBsZW1lbnQgdGlkeW1vZGVscyBwYWNrYWdlcyBzdWNoIGFzIGByc2FtcGxlYCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMgYXMgd2VsbCBhcyBjcm9zcyB2YWxpZGF0aW9uIHNldHMuCjQuIEFiaWxpdHkgdG8gdXNlIHRoZSBgcmVjaXBlc2AsIGBwYXJzbmlwYCwgYW5kIGB3b3JrZmxvd3NgIHRvIHRyYWluIGFuZCB0ZXN0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgYW5kIHJhbmRvbSBmb3Jlc3QgbW9kZWwKNS4gRGVtb25zdHJhdGUgaG93IHRvIHZpc3VhbGl6ZSBnZW8tc3BhdGlhbCBkYXRhIHVzaW5nIGBnZ3Bsb3QyYAoKPHU+KipTdGF0aXN0aWNhbCBMZWFybmluZyBPYmplY3RpdmVzOioqPC91PiAgCiAgCjEuIEJhc2ljIHVuZGVyc3RhbmRpbmcgdGhlIHV0aWxpdHkgb2YgbWFjaGluZSBsZWFybmluZyBmb3IgcHJlZGljdGlvbiBhbmQgY2xhc3NpZmljYXRpb24KMi4gVW5kZXJzdGFuZGluZyBvZiB0aGUgbmVlZCBmb3IgdHJhaW5pbmcgYW5kIHRlc3Qgc2V0cwozLiBVbmRlcnN0YW5kaW5nIG9mIHRoZSB1dGlsaXR5IG9mIGNyb3NzIHZhbGlkYXRpb24KNC4gVW5kZXJzdGFuZGluZyBvZiByYW5kb20gZm9yZXN0CjUuIEhvdyB0byBpbnRlcnByZXQgcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3IgKHJtc2UpIHRvIGFzc2VzcyBwZXJmb3JtYW5jZSBmb3IgcHJlZGljdGlvbgoKCgpgYGB7ciwgb3V0LndpZHRoID0gIjEwMHB4IiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3Bicy50d2ltZy5jb20vbWVkaWEvRGtCRnBTc1c0QUl5eUlOLnBuZyIpCmBgYAoKCldlIHdpbGwgYmVnaW4gYnkgbG9hZGluZyB0aGUgcGFja2FnZXMgdGhhdCB3ZSB3aWxsIG5lZWQ6CgpgYGB7cn0KbGlicmFyeShoZXJlKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHNraW1yKQpsaWJyYXJ5KHN1bW1hcnl0b29scykKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShjb3JycGxvdCkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoR0dhbGx5KQpsaWJyYXJ5KHRpZHltb2RlbHMpCmxpYnJhcnkod29ya2Zsb3dzKQpsaWJyYXJ5KHZpcCkKbGlicmFyeSh0dW5lKQpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkKbGlicmFyeShkb1BhcmFsbGVsKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0aWR5cikKbGlicmFyeShsd2dlb20pCmxpYnJhcnkoc2YpCmxpYnJhcnkobWFwcykKbGlicmFyeShybmF0dXJhbGVhcnRoKQpsaWJyYXJ5KHJnZW9zKQpsaWJyYXJ5KHBhdGNod29yaykKYGBgCgoKIDx1PioqUGFja2FnZXMgdXNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHk6KiogPC91PgoKUGFja2FnZSAgIHwgVXNlIGluIHRoaXMgY2FzZSBzdHVkeSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YQpbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCBDU1YgZmlsZXMKW2RwbHlyXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byB2aWV3L2FycmFuZ2UvZmlsdGVyL3NlbGVjdC9jb21wYXJlIHNwZWNpZmljIHN1YnNldHMgb2YgZGF0YSAKW3NraW1yXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEKW3N1bW1hcnl0b29sc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhIGluIGEgZGlmZmVyZW50IHN0eWxlClttYWdyaXR0cl0oaHR0cHM6Ly9tYWdyaXR0ci50aWR5dmVyc2Uub3JnL2FydGljbGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHVzZSB0aGUgYCU8PiVgIHBpcHBpbmcgb3BlcmF0b3IgCltjb3JycGxvdF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2NvcnJwbG90L3ZpZ25ldHRlcy9jb3JycGxvdC1pbnRyby5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbWFrZSBsYXJnZSBjb3JyZWxhdGlvbiBwbG90cwpbR0dhbGx5XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvR0dhbGx5L0dHYWxseS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBtYWtlIHNtYWxsZXIgY29ycmVsYXRpb24gcGxvdHMgIApbdGlkeW1vZGVsc10oaHR0cHM6Ly93d3cudGlkeW1vZGVscy5vcmcpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBsb2FkIGluIGEgc2V0IG9mIHBhY2thZ2VzIChicm9vbSwgZGlhbHMsIGluZmVyLCBwYXJzbmlwLCBwdXJyciwgcmVjaXBlcywgcnNhbXBsZSwgdGliYmxlLCB5YXJkc3RpY2spCltyc2FtcGxlXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JzYW1wbGUvYXJ0aWNsZXMvQmFzaWNzLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHNwbGl0IHRoZSBkYXRhIGludG8gdGVzdGluZyBhbmQgdHJhaW5pbmcgc2V0czsgdG8gc3BsaXQgdGhlIHRyYWluaW5nIHNldCBmb3IgY3Jvc3MtdmFsaWRhdGlvbiAgCltyZWNpcGVzXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBwcmUtcHJvY2VzcyBkYXRhIGZvciBtb2RlbGluZyBpbiBhIHRpZHkgYW5kIHJlcHJvZHVjaWJsZSB3YXkgYW5kIHRvIGV4dHJhY3QgcHJlLXByb2Nlc3NlZCBkYXRhIChtYWpvciBmdW5jdGlvbnMgYXJlIGByZWNpcGUoKWAgLCBgcHJlcCgpYCBhbmQgdmFyaW91cyB0cmFuc2Zvcm1hdGlvbiBgc3RlcF8qKClgIGZ1bmN0aW9ucywgYXMgd2VsbCBhcyBganVpY2UoKWAgLSBleHRyYWN0cyBmaW5hbCBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgYW5kIGBiYWtlKClgIC0gYXBwbGllcyByZWNpcGUgc3RlcHMgdG8gdGVzdGluZyBkYXRhKS4gU2VlIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmVjaXBlcy9yZWNpcGVzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgZm9yIG1vcmUgaW5mby4KW3BhcnNuaXBdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcGFyc25pcC8pe3RhcmdldD0iX2JsYW5rIn0gICB8IGFuIGludGVyZmFjZSB0byBjcmVhdGUgbW9kZWxzIChtYWpvciBmdW5jdGlvbnMgYXJlIGBmaXQoKWAsIGBzZXRfZW5naW5lKClgKQpbeWFyZHN0aWNrXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3lhcmRzdGljay8pe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBtb2RlbHMKW2Jyb29tXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOC8wNy9icm9vbS0wLTUtMC8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgdGlkeSBvdXRwdXQgZm9yIG91ciBtb2RlbCBmaXQgYW5kIHBlcmZvcm1hbmNlCltnZ3Bsb3QyXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYWtlIHZpc3VhbGl6YXRpb25zIHdpdGggbXVsdGlwbGUgbGF5ZXJzCltkaWFsc10oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9ibG9nLzIwMTkvMTAvZGlhbHMtMC0wLTMvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gc3BlY2lmeSBoeXBlci1wYXJhbWV0ZXIgdHVuaW5nClt0dW5lXShodHRwczovL3R1bmUudGlkeW1vZGVscy5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gcGVyZm9ybSBjcm9zcyB2YWxpZGF0aW9uLCB0dW5lIGh5cGVyLXBhcmFtZXRlcnMsIGFuZCBnZXQgcGVyZm9ybWFuY2UgbWV0cmljcwpbd29ya2Zsb3dzXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvd29ya2Zsb3dzL3ZlcnNpb25zLzAuMS4xKXt0YXJnZXQ9Il9ibGFuayJ9fCB0byBjcmVhdGUgbW9kZWxpbmcgd29ya2Zsb3cgdG8gc3RyZWFtbGluZSB0aGUgbW9kZWxpbmcgcHJvY2VzcwpbdmlwXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdmlwL3ZpcC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgdmFyaWFibGUgaW1wb3J0YW5jZSBwbG90cwpbcmFuZG9tRm9yZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIHRoZSByYW5kb20gZm9yZXN0IGFuYWx5c2lzCltkb1BhcmFsbGVsXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZG9QYXJhbGxlbC9kb1BhcmFsbGVsLnBkZikgfCB0byBmaXQgY3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGVzIGluIHBhcmFsbGVsIApbc3RyaW5ncl0oaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvc3RyaW5nci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFuaXB1bGF0ZSB0aGUgdGV4dCB0aGUgbWFwIGRhdGEKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzZXBhcmF0ZSBkYXRhIHdpdGhpbiBhIGNvbHVtbiBpbnRvIG11bHRpcGxlIGNvbHVtbnMKW3JuYXR1cmFsZWFydGhdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ybmF0dXJhbGVhcnRoL1JFQURNRS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IHRoZSBnZW9tZXRyeSBkYXRhIGZvciB0aGUgZWFydGggdG8gcGxvdCB0aGUgVVMKW21hcHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYXBzL21hcHMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IG1hcCBkYXRhYmFzZSBkYXRhIGFib3V0IGNvdW50aWVzIHRvIGRyYXcgdGhlbSBvbiBvdXIgVVMgbWFwCltzZl0oaHR0cHM6Ly9yLXNwYXRpYWwuZ2l0aHViLmlvL3NmLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGNvbnZlcnQgdGhlIG1hcCBkYXRhIGludG8gYSBkYXRhIGZyYW1lCltsd2dlb21dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9sd2dlb20vbHdnZW9tLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHVzZSB0aGUgYHNmYCBmdW5jdGlvbiB0byBjb252ZXJ0IG1hcCBnZW9ncmFwaGljYWwgZGF0YQpbcmdlb3NdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZ2Vvcy9yZ2Vvcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byB1c2UgZ2VvbWV0cnkgZGF0YQpbcGF0Y2h3b3JrXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcGF0Y2h3b3JrL3BhdGNod29yay5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBhbGxvdyBwbG90cyB0byBiZSBjb21iaW5lZApfX18KCgpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIApVbmxlc3Mgd2UgaGF2ZSBvdmVybGFwcGluZyBmdW5jdGlvbiBuYW1lcywgdGhpcyBpcyBub3QgbmVjZXNzYXJ5LCBidXQgd2Ugd2lsbCBpbmNsdWRlIGl0IGhlcmUgdG8gYmUgaW5mb3JtYXRpdmUgYWJvdXQgd2hlcmUgdGhlIGZ1bmN0aW9ucyB3ZSB3aWxsIHVzZSBjb21lIGZyb20uCgoKIyAqKkNvbnRleHQqKgoqKioKClRoZSBbU3RhdGUgb2YgR2xvYmFsIEFpcl0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9IGlzIGEgcmVwb3J0IHJlbGVhc2VkIGV2ZXJ5IHllYXIgdG8gY29tbXVuaWNhdGUgdGhlIGltcGFjdCBvZiBhaXIgcG9sbHV0aW9uIG9uIHB1YmxpYyBoZWFsdGguIAoKVGhlIFtTdGF0ZSBvZiBHbG9iYWwgQWlyIDIwMTkgcmVwb3J0XShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9yZXBvcnQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CndoaWNoIHVzZXMgZGF0YSBmcm9tIDIwMTcgc3RhdGVkIHRoYXQ6Cgo+IEFpciBwb2xsdXRpb24gaXMgdGhlICoqZmlmdGgqKiBsZWFkaW5nIHJpc2sgZmFjdG9yIGZvciBtb3J0YWxpdHkgd29ybGR3aWRlLiBJdCBpcyByZXNwb25zaWJsZSBmb3IgbW9yZQpkZWF0aHMgdGhhbiBtYW55IGJldHRlci1rbm93biByaXNrIGZhY3RvcnMgc3VjaCBhcyBtYWxudXRyaXRpb24sIGFsY29ob2wgdXNlLCBhbmQgcGh5c2ljYWwgaW5hY3Rpdml0eS4KRWFjaCB5ZWFyLCAqKm1vcmUqKiBwZW9wbGUgZGllIGZyb20gYWlyIHBvbGx1dGlvbuKAk3JlbGF0ZWQgZGlzZWFzZSB0aGFuIGZyb20gcm9hZCAqKnRyYWZmaWMgaW5qdXJpZXMqKiBvciAqKm1hbGFyaWEqKi4KCjxwIGFsaWduPSJjZW50ZXIiPgo8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly93d3cuaGVhbHRoZWZmZWN0cy5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9Tb0dBLUZpZ3VyZXMtMDEuanBnIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9yZXBvcnQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CgpUaGUgcmVwb3J0IGFsc28gc3RhdGVkIHRoYXQ6Cgo+IEluIDIwMTcsIGFpciBwb2xsdXRpb24gaXMgZXN0aW1hdGVkIHRvIGhhdmUgY29udHJpYnV0ZWQgdG8gY2xvc2UgdG8gNSBtaWxsaW9uCmRlYXRocyBnbG9iYWxseSDigJQgbmVhcmx5ICoqMSBpbiBldmVyeSAxMCBkZWF0aHMqKi4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCIyMDE3ZGVhdGhzLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfZmFjdF9zaGVldC5wZGYpe3RhcmdldD0iX2JsYW5rIn0KClRoZSBbU3RhdGUgb2YgR2xvYmFsIEFpciAyMDE4IHJlcG9ydF0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhLTIwMTgtcmVwb3J0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSB1c2luZyBkYXRhIGZyb20gMjAxNiB3aGljaCBzZXBhcmF0ZWQgZGlmZmVyZW50IHR5cGVzIG9mIGFpciBwb2xsdXRpb24sIGZvdW5kIHRoYXQgKipwYXJ0aWN1bGF0ZSBwb2xsdXRpb24gd2FzIHBhcnRpY3VsYXJseSBhc3NvY2lhdGVkIHdpdGggbW9ydGFsaXR5KiouCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiMjAxN21vcnRhbGl0eS5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYS0yMDE4LXJlcG9ydC5wZGYpCgpUaGUgMjAxOSByZXBvcnQgc2hvd3MgdGhhdCB0aGUgaGlnaGVzdCBsZXZlbHMgb2YgZmluZSBwYXJ0aWN1bGF0ZSBwb2xsdXRpb24gb2NjdXJzIGluIEFmcmljYSBhbmQgQXNpYSBhbmQgdGhhdDoKCj4gTW9yZSB0aGFuICoqOTAlKiogb2YgcGVvcGxlIHdvcmxkd2lkZSBsaXZlIGluIGFyZWFzICoqZXhjZWVkaW5nKiogdGhlIFdvcmxkIEhlYWx0aCBPcmdhbml6YXRpb24gKFdITykgKipHdWlkZWxpbmUqKiBmb3IgaGVhbHRoeSBhaXIuIE1vcmUgdGhhbiBoYWxmIGxpdmUgaW4gYXJlYXMgdGhhdCBkbyBub3QgZXZlbiBtZWV0IFdITydzIGxlYXN0LXN0cmluZ2VudCBhaXIgcXVhbGl0eSB0YXJnZXQuCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiUE13b3JsZC5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYV8yMDE5X2ZhY3Rfc2hlZXQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CgpMb29raW5nIGF0IHRoZSBVUyBzcGVjaWZpY2FsbHksIGFpciBwb2xsdXRpb24gbGV2ZWxzIGFyZSBnZW5lcmFsbHkgaW1wcm92aW5nLCB3aXRoIGRlY2xpbmluZyBuYXRpb25hbCBhaXIgcG9sbHV0YW50IGNvbmNlbnRyYXRpb24gYXZlcmFnZXMgYXMgc2hvd24gZnJvbSB0aGUgMjAxOSBbKk91ciBOYXRpb24ncyBBaXIqXShodHRwczovL2dpc3B1Yi5lcGEuZ292L2Fpci90cmVuZHNyZXBvcnQvMjAxOS8jaG9tZSl7dGFyZ2V0PSJfYmxhbmsifSByZXBvcnQgZnJvbSB0aGUgVVMgRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSAoRVBBKTogCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiVVMucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2dpc3B1Yi5lcGEuZ292L2Fpci90cmVuZHNyZXBvcnQvMjAxOS9kb2N1bWVudGF0aW9uL0FpclRyZW5kc19GbHllci5wZGYpe3RhcmdldD0iX2JsYW5rIn0KCkhvd2V2ZXIsIGFpciBwb2xsdXRpb24gKipjb250aW51ZXMgdG8gY29udHJpYnV0ZSB0byBoZWFsdGggcmlzayBmb3IgQW1lcmljYW5zKiosIGluIHBhcnRpY3VsYXIgaW4gKipyZWdpb25zIHdpdGggaGlnaGVyIHRoYW4gbmF0aW9uYWwgYXZlcmFnZSByYXRlcyoqIG9mIHBvbGx1dGlvbiB0aGF0IGFjdHVhbGx5IGF0IHRpbWUgZXhjZWVkIHRoZSBXSE8ncyByZWNvbW1lbmRlZCBsZXZlbC4gClRodXMsIGl0IGlzIGltcG9ydGFudCB0byBvYnRhaW4gaGlnaCBzcGF0aWFsIGdyYW51bGFyaXR5IGluIGVzdGltYXRlcyBvZiBhaXIgcG9sbHV0aW9uIGluIG9yZGVyIHRvIGlkZW50aWZ5IGxvY2F0aW9ucyB3aGVyZSBwb3B1bGF0aW9ucyBhcmUgZXhwZXJpZW5jaW5nIGhhcm1mdWwgbGV2ZWxzIG9mIGV4cG9zdXJlLgoKWW91IGNhbiBzZWUgdGhhdCBjdXJyZW50IGFpciBxdWFsaXR5IGNvbmRpdGlvbnMgYXQgdGhpcyBbd2Vic2l0ZV0oaHR0cHM6Ly9hcWljbi5vcmcvY2l0eS91c2EvKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCB5b3Ugd2lsbCBub3RpY2UgdmFyaWF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgY2l0aWVzLgoKRm9yIGV4YW1wbGUsIGhlcmUgYXJlIHRoZSBjb25kaXRpb25zIGluIFRvcGVrYSBLYW5zYXMgYXQgdGhlIHRpbWUgdGhpcyBjYXNlIHN0dWR5IHdhcyBjcmVhdGVkOgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIkthbnNhcy5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vYXFpY24ub3JnL2NpdHkvdXNhLykKCkl0IHJlcG9ydHMgcGFydGljdWxhdGUgdmFsdWVzIHVzaW5nIHdoYXQgaXMgY2FsbGVkIHRoZSBbQWlyIFF1YWxpdHkgSW5kZXhdKGh0dHBzOi8vd3d3LmFpcm5vdy5nb3YvaW5kZXguY2ZtP2FjdGlvbj1hcWliYXNpY3MuYXFpKXt0YXJnZXQ9Il9ibGFuayJ9IChBUUkpLgpUaGlzIFtjYWxjdWxhdG9yXShodHRwczovL2Fpcm5vdy5nb3YvaW5kZXguY2ZtP2FjdGlvbj1haXJub3cuY2FsY3VsYXRvcil7dGFyZ2V0PSJfYmxhbmsifSBpbmRpY2F0ZXMgdGhhdCAxMTQgQVFJIGlzIGVxdWl2YWxlbnQgdG8gNDAuNyB1Zy9tXjNeIGFuZCBpcyBjb25zaWRlcmVkIHVuaGVhbHRoeSBmb3Igc2Vuc2l0aXZlIGluZGl2aWR1YWxzLgpUaHVzLCBzb21lIGFyZWFzIGV4Y2VlZCB0aGUgV0hPIGFubnVhbCBleHBvc3VyZSBndWlkZWxpbmUgKDEwIHVnL21eM14pIGFuZCB0aGlzIG1heSBhZHZlcnNlbHkgYWZmZWN0IHRoZSBoZWFsdGggb2YgcGVvcGxlIGxpdmluZyBpbiB0aGVzZSBsb2NhdGlvbnMuCgpBZHZlcnNlIGhlYWx0aCBlZmZlY3RzIGhhdmUgYmVlbiBhc3NvY2lhdGVkIHdpdGggcG9wdWxhdGlvbnMgZXhwZXJpZW5jaW5nIGhpZ2hlciBwb2xsdXRpb24gZXhwb3N1cmUgZGVzcGl0ZSB0aGUgbGV2ZWxzIGJlaW5nIGJlbG93IHN1Z2dlc3RlZCBndWlkZWxpbmVzLiAKQWxzbywgaXQgYXBwZWFycyB0aGF0IHRoZSBjb21wb3NpdGlvbiBvZiB0aGUgcGFydGljdWxhdGUgbWF0dGVyIGFuZCB0aGUgaW5mbHVlbmNlIG9mIG90aGVyIGRlbW9ncmFwaGljIGZhY3RvcnMgbWF5IG1ha2Ugc3BlY2lmaWMgcG9wdWxhdGlvbnMgbW9yZSBhdCByaXNrIGZvciBhZHZlcnNlIGhlYWx0aCBlZmZlY3RzIGR1ZSB0byBhaXIgcG9sbHV0aW9uLiAKRm9yIGV4YW1wbGUsIHNlZSB0aGlzIFthcnRpY2xlXShodHRwczovL3d3dy5uZWptLm9yZy9kb2kvZnVsbC8xMC4xMDU2L05FSk1vYTE3MDI3NDcpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgZGV0YWlscy4KClRoZSBtb25pdG9yIGRhdGEgdGhhdCB3ZSB3aWxsIHVzZSBpbiB0aGlzIGNhc2Ugc3R1ZHkgY29tZSBmcm9tIGEgc3lzdGVtIG9mIG1vbml0b3JzIGluIHdoaWNoIHJvdWdobHkgOTAlIGFyZSBsb2NhdGVkIHdpdGhpbiBjaXRpZXMuIApIZW5jZSwgdGhlcmUgaXMgYW4gKiplcXVpdHkgaXNzdWUqKiBpbiB0ZXJtcyBvZiBjYXB0dXJpbmcgdGhlIGFpciBwb2xsdXRpb24gbGV2ZWxzIG9mIG1vcmUgcnVyYWwgYXJlYXMuIApUbyBnZXQgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIHBvbGx1dGlvbiBleHBvc3VyZXMgZm9yIHRoZSBpbmRpdmlkdWFscyBsaXZpbmcgaW4gdGhlc2UgYXJlYXMsIG1ldGhvZHMgbGlrZSBtYWNoaW5lIGxlYXJuaW5nIGNhbiBiZSB1c2VmdWwgdG8gZXN0aW1hdGUgYWlyIHBvbGx1dGlvbiBsZXZlbHMgaW4gKiphcmVhcyB3aXRoIGxpdHRsZSB0byBubyBtb25pdG9yaW5nKiouIApTcGVjaWZpY2FsbHksIHRoZXNlIG1ldGhvZHMgY2FuIGJlIHVzZWQgdG8gZXN0aW1hdGUgYWlyIHBvbGx1dGlvbiBpbiB0aGVzZSBsb3cgbW9uaXRvcmluZyBhcmVhcyBzbyB0aGF0IHdlIGNhbiBtYWtlIGEgbWFwIGxpa2UgdGhpcyB3aGVyZSB3ZSBoYXZlIGFubnVhbCBlc3RpbWF0ZXMgZm9yIGFsbCBvZiB0aGUgY29udGlndW91cyBVUzoKCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjYwMCIgc3JjPSJodHRwczovL2FyYy1hbmdsZXJmaXNoLXdhc2hwb3N0LXByb2Qtd2FzaHBvc3QuczMuYW1hem9uYXdzLmNvbS9wdWJsaWMvU0FXT0VHQlhNVkdRN0FTNVBaNlVVT1g2RlkucG5nIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5nb29nbGUuY29tL3VybD9zYT1pJnVybD1odHRwcyUzQSUyRiUyRnd3dy53YXNoaW5ndG9ucG9zdC5jb20lMkZidXNpbmVzcyUyRjIwMTklMkYxMCUyRjIzJTJGYWlyLXBvbGx1dGlvbi1pcy1nZXR0aW5nLXdvcnNlLWRhdGEtc2hvdy1tb3JlLXBlb3BsZS1hcmUtZHlpbmclMkYmcHNpZz1BT3ZWYXczdi1aRFRCUG5MUDJNWXRLZjNVbmRqJnVzdD0xNTg1Nzg0NDc5MDY4MDAwJnNvdXJjZT1pbWFnZXMmY2Q9dmZlJnZlZD0wQ0FJUWpSeHFGd29UQ1BDeW45Znh4ZWdDRlFBQUFBQWRBQUFBQUJBZCl7dGFyZ2V0PSJfYmxhbmsifQoKVGhpcyBpcyB3aGF0IHdlIGFpbSB0byBhY2hpZXZlIGluIHRoaXMgY2FzZSBzdHVkeS4KCiMgKipMaW1pdGF0aW9ucyoqCioqKgoKVGhlcmUgYXJlIHNvbWUgaW1wb3J0YW50IGNvbnNpZGVyYXRpb25zIHJlZ2FyZGluZyB0aGUgZGF0YSBhbmFseXNpcyBpbiB0aGlzIGNhc2Ugc3R1ZHkgdG8ga2VlcCBpbiBtaW5kOiAKCjEuIFRoZSBkYXRhIGRvIG5vdCBpbmNsdWRlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBjb21wb3NpdGlvbiBvZiBwYXJ0aWN1bGF0ZSBtYXR0ZXIuIERpZmZlcmVudCB0eXBlcyBvZiBwYXJ0aWN1bGF0ZXMgbWF5IGJlIG1vcmUgYmVuaWduIG9yIGRlbGV0ZXJpb3VzIGZvciBoZWFsdGggb3V0Y29tZXMuCgoyLiBPdXRkb29yIHBvbGx1dGlvbiBsZXZlbHMgYXJlIG5vdCBuZWNlc3NhcmlseSBhbiBpbmRpY2F0aW9uIG9mIGluZGl2aWR1YWwgZXhwb3N1cmVzLiBQZW9wbGUgc3BlbmQgZGlmZmVyaW5nIGFtb3VudHMgb2YgdGltZSBpbmRvb3JzIGFuZCBvdXRkb29ycyBhbmQgYXJlIGV4cG9zZWQgdG8gZGlmZmVyZW50IHBvbGx1dGlvbiBsZXZlbHMgaW5kb29ycy4gUmVzZWFyY2hlcnMgYXJlIG5vdyBkZXZlbG9waW5nIHBlcnNvbmFsIG1vbml0b3Jpbmcgc3lzdGVtcyB0byB0cmFjayBhaXIgcG9sbHV0aW9uIGxldmVscyBvbiB0aGUgcGVyc29uYWwgbGV2ZWwuCgozLiBPdXIgYW5hbHlzaXMgd2lsbCB1c2UgYW5udWFsIG1lYW4gZXN0aW1hdGVzIG9mIHBvbGx1dGlvbiBsZXZlbHMsIGJ1dCB0aGVzZSBjYW4gdmFyeSBncmVhdGx5IGJ5IHNlYXNvbiwgZGF5IGFuZCBldmVuIGhvdXIuIFRoZXJlIGFyZSBkYXRhIHNvdXJjZXMgdGhhdCBoYXZlIGZpbmVyIGxldmVscyBvZiB0ZW1wb3JhbCBkYXRhLCBob3dldmVyIHdlIGFyZSBpbnRlcmVzdGVkIGluIGxvbmcgdGVybSBleHBvc3VyZXMsIGFzIHRoZXNlIGFwcGVhciB0byBiZSB0aGUgbW9zdCBpbmZsdWVudGlhbCBmb3IgaGVhbHRoIG91dGNvbWVzLCBzbyB3ZSBjaG9zZSB0byB1c2UgYW5udWFsIGxldmVsIGRhdGEuIAoKCiMgKipXaGF0IGFyZSB0aGUgZGF0YT8qKiB7I3doYXRhcmV0aGVkYXRhfQoqKioKCldoZW4gdXNpbmcgbWFjaGluZSBsZWFybmluZyBmb3IgcHJlZGljdGlvbiwgdGhlcmUgYXJlIHR3byBtYWluIHR5cGVzIG9mIGRhdGEgb2YgaW50ZXJlc3Q6CgoxLiBBbiAqKmNvbnRpbnVvdXMqKiBvdXRjb21lIHZhcmlhYmxlIHRoYXQgd2Ugd2FudCB0byBwcmVkaWN0IAoyLiBBIHNldCBvZiBmZWF0dXJlKHMpIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSB0aGF0IHdlIHVzZSB0byBwcmVkaWN0IHRoZSBvdXRjb21lIHZhcmlhYmxlCgpUaGUgKipvdXRjb21lIHZhcmlhYmxlKiogaXMgd2hhdCBhcmUgdHJ5aW5nIHRvICoqcHJlZGljdCoqLiAKVG8gYnVpbGQgKG9yIHRyYWluKSBvdXIgbW9kZWwsIHdlIHVzZSBib3RoIHRoZSBvdXRjb21lIGFuZCBmZWF0dXJlcy4KVGhlIGdvYWwgaXMgdG8gaWRlbnRpZnkgaW5mb3JtYXRpdmUgZmVhdHVyZXMgdGhhdCBjYW4gZXhwbGFpbiBhIGxhcmdlIGFtb3VudCBvZiB2YXJpYXRpb24gaW4gb3VyIG91dGNvbWUgdmFyaWFibGUuIApVc2luZyB0aGlzIG1vZGVsLCB3ZSBjYW4gdGhlbiBwcmVkaWN0IHRoZSBvdXRjb21lIGZyb20gbmV3IG9ic2VydmF0aW9ucyB3aXRoIHRoZSBzYW1lIGZlYXR1cmVzIHdoZXJlIGhhdmUgbm90IG9ic2VydmVkIHRoZSBvdXRjb21lLiAKCkFzIGEgc2ltcGxlIGV4YW1wbGUsIGltYWdpbmUgdGhhdCB3ZSBoYXZlIGRhdGEgYWJvdXQgdGhlIHNhbGVzIGFuZCBjaGFyYWN0ZXJpc3RpY3Mgb2YgY2FycyBmcm9tIGxhc3QgeWVhciBhbmQgd2Ugd2FudCB0byBwcmVkaWN0IHdoaWNoIGNhcnMgbWlnaHQgc2VsbCB3ZWxsIHRoaXMgeWVhci4gCldlIGRvIG5vdCBoYXZlIHRoZSBzYWxlcyBkYXRhIHlldCBmb3IgdGhpcyB5ZWFyLCBidXQgd2UgZG8ga25vdyB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIG91ciBjYXJzIGZvciB0aGlzIHllYXIuIApXZSBjYW4gYnVpbGQgYSBtb2RlbCBvZiB0aGUgY2hhcmFjdGVyaXN0aWNzIHRoYXQgZXhwbGFpbmVkIHNhbGVzIGxhc3QgeWVhciB0byBlc3RpbWF0ZSB3aGF0IGNhcnMgbWlnaHQgc2VsbCB3ZWxsIHRoaXMgeWVhci4gCkluIHRoaXMgY2FzZSwgb3VyIG91dGNvbWUgdmFyaWFibGUgaXMgdGhlIHNhbGVzIG9mIGNhcnMsIHdoaWxlIHRoZSBkaWZmZXJlbnQgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBjYXJzIG1ha2UgdXAgb3VyIGZlYXR1cmVzLgoKIyMjIFN0YXJ0IHdpdGggYSBxdWVzdGlvbgoKVGhpcyBpcyB0aGUgbW9zdCBjb21tb25seSBtaXNzZWQgc3RlcCB3aGVuIGRldmVsb3BpbmcgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobS4gCk1hY2hpbmUgbGVhcm5pbmcgY2FuIHZlcnkgZWFzaWx5IGJlIHR1cm5lZCBpbnRvIGFuIGVuZ2luZWVyaW5nIHByb2JsZW0uIApKdXN0IGR1bXAgdGhlIG91dGNvbWUgYW5kIHRoZSBmZWF0dXJlcyBpbnRvIGEgYmxhY2sgYm94IGFsZ29yaXRobSBhbmQgdmlvbGEhIApCdXQgdGhpcyBraW5kIG9mIHRoaW5raW5nIGNhbiBsZWFkIHRvIG1ham9yIHByb2JsZW1zLiBJbiBnZW5lcmFsIGdvb2QgbWFjaGluZSBsZWFybmluZyBxdWVzdGlvbnM6CgoxLiBIYXZlIGEgcGxhdXNpYmxlIGV4cGxhbmF0aW9uIGZvciB3aHkgdGhlIGZlYXR1cmVzIHByZWRpY3QgdGhlIG91dGNvbWUuIAoyLiBDb25zaWRlciBwb3RlbnRpYWwgdmFyaWF0aW9uIGluIGJvdGggdGhlIGZlYXR1cmVzIGFuZCB0aGUgb3V0Y29tZSBvdmVyIHRpbWUKMy4gQXJlIGNvbnNpc3RlbnRseSByZS1ldmFsdWF0ZWQgb24gY3JpdGVyaWEgMSBhbmQgMiBvdmVyIHRpbWUuIAoKSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSB3YW50IHRvICoqcHJlZGljdCoqIGFpciBwb2xsdXRpb24gbGV2ZWxzLiAKVG8gYnVpbGQgdGhpcyBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSwgb3VyICoqb3V0Y29tZSB2YXJpYWJsZSoqIGlzIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIChQTX4yLjV+KSBjYXB0dXJlZCBmcm9tIGFpciBwb2xsdXRpb24gbW9uaXRvcnMgaW4gdGhlIGNvbnRpZ3VvdXMgVVMgZnJvbSAyMDA4LiAKT3VyICoqZmVhdHVyZXMqKiAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgaW5jbHVkZSBkYXRhIGFib3V0IHBvcHVsYXRpb24gZGVuc2l0eSwgcm9hZCBkZW5zaXR5LCB1cmJhbml6YXRpb24gbGV2ZWxzLCBhbmQgTkFTQSBzYXRlbGxpdGUgZGF0YS4gCgpBbGwgb2Ygb3VyIGRhdGEgd2FzIHByZXZpb3VzbHkgY29sbGVjdGVkIGJ5IGEgW3Jlc2VhcmNoZXJdKGh0dHA6Ly93d3cuYmlvc3RhdC5qaHNwaC5lZHUvfnJwZW5nLykgYXQgdGhlIFtKb2hucyBIb3BraW5zIFNjaG9vbCBvZiBQdWJsaWMgSGVhbHRoXShodHRwczovL3d3dy5qaHNwaC5lZHUvKSB3aG8gc3R1ZGllcyBhaXIgcG9sbHV0aW9uIGFuZCBjbGltYXRlIGNoYW5nZS4gCgoKIyMjIE91ciBvdXRjb21lIHZhcmlhYmxlCgpUaGUgbW9uaXRvciBkYXRhIHRoYXQgd2Ugd2lsbCBiZSB1c2luZyBjb21lcyBmcm9tICoqW2dyYXZpbWV0cmljIG1vbml0b3JzXShodHRwczovL3B1YmxpY2xhYi5vcmcvd2lraS9maWx0ZXItcG0pe3RhcmdldD0iX2JsYW5rIn0qKiAoc2VlIHBpY3R1cmUgYmVsb3cpIG9wZXJhdGVkIGJ5IHRoZSBVUyBbRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSAoRVBBKV0oaHR0cHM6Ly93d3cuZXBhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjEwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwibW9uaXRvci5wbmciKSkKYGBgCgojIyMjI1tpbWFnZSBjdXJ0ZXN5IG9mIFtLaXJzdGVuIEtvZWhsZXJdKGh0dHBzOi8vd3d3Lmpoc3BoLmVkdS9mYWN1bHR5L2RpcmVjdG9yeS9wcm9maWxlLzI5Mjgva2lyc3Rlbi1rb2VobGVyKV0KClRoZXNlIG1vbml0b3JzIHVzZSBhIGZpbHRyYXRpb24gc3lzdGVtIHRvIHNwZWNpZmljYWxseSBjYXB0dXJlIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyLiAKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iMTUwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJmaWx0ZXIucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3B1YmxpY2xhYi5vcmcvd2lraS9maWx0ZXItcG0pe3RhcmdldD0iX2JsYW5rIn0KClRoZSB3ZWlnaHQgb2YgdGhpcyBwYXJ0aWN1bGF0ZSBtYXR0ZXIgaXMgbWFudWFsbHkgbWVhc3VyZWQgZGFpbHkgb3Igd2Vla2x5LiAKRm9yIHRoZSBFUEEgc3RhbmRhcmQgb3BlcmF0aW5nIHByb2NlZHVyZSBmb3IgUE0gZ3JhdmltZXRyaWMgYW5hbHlzaXMgaW4gMjAwOCwgd2UgcmVmZXIgdGhlIHJlYWRlciB0byBbaGVyZV0oaHR0cHM6Ly93d3czLmVwYS5nb3YvdHRuYW10aTEvZmlsZXMvYW1iaWVudC9wbTI1L3NwZWMvUlRJR3Jhdk1hc3NTT1BGSU5BTC5wZGYpe3RhcmdldD0iX2JsYW5rIn0uCgo8ZGV0YWlscz48c3VtbWFyeT5Gb3IgbW9yZSBvbiBHcmF2aW1ldHJpYyBhbmFseXNpcywgeW91IGNhbiBleHBhbmQgaGVyZSA8L3N1bW1hcnk+CgpHcmF2aW1ldHJpYyBhbmFseXNpcyBpcyBhbHNvIHVzZWQgZm9yIFtlbWlzc2lvbiB0ZXN0aW5nXShodHRwczovL3d3dy5tdC5jb20vdXMvZW4vaG9tZS9hcHBsaWNhdGlvbnMvTGFib3JhdG9yeV93ZWlnaGluZy9lbWlzc2lvbnMtdGVzdGluZy1wYXJ0aWN1bGF0ZS1tYXR0ZXIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4gClRoZSBzYW1lIGlkZWEgYXBwbGllczogYSBmcmVzaCBmaWx0ZXIgaXMgYXBwbGllZCBhbmQgdGhlIGRlc2lyZWQgYW1vdW50IG9mIHRpbWUgcGFzc2VzLCB0aGVuIHRoZSBmaWx0ZXIgaXMgcmVtb3ZlZCBhbmQgd2VpZ2hlZC4gCgpUaGVyZSBhcmUgW290aGVyIG1vbml0b3Jpbmcgc3lzdGVtc10oaHR0cHM6Ly93d3cuc2Vuc2lyaW9uLmNvbS9lbi9hYm91dC11cy9uZXdzcm9vbS9zZW5zaXJpb24tc3BlY2lhbGlzdC1hcnRpY2xlcy9wYXJ0aWN1bGF0ZS1tYXR0ZXItc2Vuc2luZy1mb3ItYWlyLXF1YWxpdHktbWVhc3VyZW1lbnRzLyl7dGFyZ2V0PSJfYmxhbmsifSB0aGF0IGNhbiBwcm92aWRlIGhvdXJseSBtZWFzdXJlbWVudHMsIGJ1dCB3ZSB3aWxsIG5vdCBiZSB1c2luZyBkYXRhIGZyb20gdGhlc2UgbW9uaXRvcnMgaW4gb3VyIGFuYWx5c2lzLiAKR3JhdmltZXRyaWMgYW5hbHlzaXMgaXMgY29uc2lkZXJlZCB0byBiZSBhbW9uZyB0aGUgbW9zdCBhY2N1cmF0ZSBtZXRob2RzIGZvciBtZWFzdXJpbmcgcGFydGljdWxhdGUgbWF0dGVyLgoKPC9kZXRhaWxzPgoKSW4gb3VyIGRhdGEgc2V0LCB0aGUgYHZhbHVlYCBjb2x1bW4gaW5kaWNhdGVzIHRoZSBQTX4yLjV+IG1vbml0b3IgYXZlcmFnZSBmb3IgMjAwOCBpbiBtYXNzIG9mIGZpbmUgcGFydGljbGVzL3ZvbHVtZSBvZiBhaXIgZm9yIDg3NiBncmF2aW1ldHJpYyBtb25pdG9ycy4gClRoZSB1bml0cyBhcmUgbWljcm9ncmFtcyBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciAoUE0pIHRoYXQgaXMgbGVzcyB0aGFuIDIuNSBtaWNyb21ldGVycyBpbiBkaWFtZXRlciBwZXIgY3ViaWMgbWV0ZXIgb2YgYWlyIC0gbWFzcyBjb25jZW50cmF0aW9uICh1Zy9tXjNeKS4KUmVjYWxsIHRoZSBXSE8gZXhwb3N1cmUgZ3VpZGVsaW5lIGlzIDwgMTAgdWcvbV4zXiBvbiBhdmVyYWdlIGFubnVhbGx5IGZvciBQTX4yLjV+LgoKIyMjIE91ciBmZWF0dXJlcyAocHJlZGljdG9yIHZhcmlhYmxlcykgCgpUaGVyZSBhcmUgNDggZmVhdHVyZXMgd2l0aCB2YWx1ZXMgZm9yIGVhY2ggb2YgdGhlIDg3NiBtb25pdG9ycyAob2JzZXJ2YXRpb25zKS4gClRoZSBkYXRhIGNvbWVzIGZyb20gdGhlIFVTIFtFbnZpcm9ubWVudGFsIFByb3RlY3Rpb24gQWdlbmN5IChFUEEpXShodHRwczovL3d3dy5lcGEuZ292Lyl7dGFyZ2V0PSJfYmxhbmsifSwgdGhlIFtOYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24gKE5BU0EpXShodHRwczovL3d3dy5uYXNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0sIHRoZSBVUyBbQ2Vuc3VzXShodHRwczovL3d3dy5jZW5zdXMuZ292L2Fib3V0L3doYXQvY2Vuc3VzLWF0LWEtZ2xhbmNlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0sIGFuZCB0aGUgW05hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3MgKE5DSFMpXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvYWJvdXQvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9LgoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gc2VlIGEgdGFibGUgYWJvdXQgdGhlIHNldCBvZiBmZWF0dXJlcyA8L3N1bW1hcnk+CgpWYXJpYWJsZSAgIHwgRGV0YWlscyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tCioqaWQqKiAgfCBNb25pdG9yIG51bWJlciAgPGJyPiAtLSB0aGUgY291bnR5IG51bWJlciBpcyBpbmRpY2F0ZWQgYmVmb3JlIHRoZSBkZWNpbWFsIDxicj4gLS0gdGhlIG1vbml0b3IgbnVtYmVyIGlzIGluZGljYXRlZCBhZnRlciB0aGUgZGVjaW1hbCA8YnI+ICAqKkV4YW1wbGUqKjogMTA3My4wMDIzICBpcyBKZWZmZXJzb24gY291bnR5ICgxMDczKSBhbmQgLjAwMjMgb25lIG9mIDggbW9uaXRvcnMgCioqZmlwcyoqIHwgRmVkZXJhbCBpbmZvcm1hdGlvbiBwcm9jZXNzaW5nIHN0YW5kYXJkIG51bWJlciBmb3IgdGhlIGNvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkIDxicj4gLS0gNSBkaWdpdCBpZCBjb2RlIGZvciBjb3VudGllcyAoemVybyBpcyBvZnRlbiB0aGUgZmlyc3QgdmFsdWUgYW5kIHNvbWV0aW1lcyBpcyBub3Qgc2hvd24pIDxicj4gLS0gdGhlIGZpcnN0IDIgbnVtYmVycyBpbmRpY2F0ZSB0aGUgc3RhdGUgPGJyPiAtLSB0aGUgbGFzdCB0aHJlZSBudW1iZXJzIGluZGljYXRlIHRoZSBjb3VudHkgPGJyPiAgKipFeGFtcGxlKio6IEFsYWJhbWEncyBzdGF0ZSBjb2RlIGlzIDAxIGJlY2F1c2UgaXQgaXMgZmlyc3QgYWxwaGFiZXRpY2FsbHkgPGJyPiAobm90ZTogQWxhc2thIGFuZCBIYXdhaWkgYXJlIG5vdCBpbmNsdWRlZCBiZWNhdXNlIHRoZXkgYXJlIG5vdCBwYXJ0IG9mIHRoZSBjb250aWd1b3VzIFVTKSAgCioqTGF0KiogfCBMYXRpdHVkZSBvZiB0aGUgbW9uaXRvciBpbiBkZWdyZWVzICAKKipMb24qKiB8IExvbmdpdHVkZSBvZiB0aGUgbW9uaXRvciBpbiBkZWdyZWVzICAKKipzdGF0ZSoqIHwgU3RhdGUgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZAoqKmNvdW50eSoqIHwgQ291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQKKipjaXR5KiogfCBDaXR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQKKipDTUFRKiogIHwgRXN0aW1hdGVkIHZhbHVlcyBvZiBhaXIgcG9sbHV0aW9uIGZyb20gYSBjb21wdXRhdGlvbmFsIG1vZGVsIGNhbGxlZCBbKipDb21tdW5pdHkgTXVsdGlzY2FsZSBBaXIgUXVhbGl0eSAoQ01BUSkqKl0oaHR0cHM6Ly93d3cuZXBhLmdvdi9jbWFxKXt0YXJnZXQ9Il9ibGFuayJ9IDxicj4gLS0gIEEgbW9uaXRvcmluZyBzeXN0ZW0gdGhhdCBzaW11bGF0ZXMgdGhlIHBoeXNpY3Mgb2YgdGhlIGF0bW9zcGhlcmUgdXNpbmcgY2hlbWlzdHJ5IGFuZCB3ZWF0aGVyIGRhdGEgdG8gcHJlZGljdCB0aGUgYWlyIHBvbGx1dGlvbiA8YnI+IC0tICoqKkRvZXMgbm90IHVzZSBhbnkgb2YgdGhlIFBNfjIuNX4gZ3JhdmltZXRyaWMgbW9uaXRvcmluZyBkYXRhLioqKiAoVGhlcmUgaXMgYSB2ZXJzaW9uIHRoYXQgZG9lcyB1c2UgdGhlIGdyYXZpbWV0cmljIG1vbml0b3JpbmcgZGF0YSwgYnV0IG5vdCB0aGlzIG9uZSEpIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBFUEEKKip6Y3RhKiogfCBbWmlwIENvZGUgVGFidWxhdGlvbiBBcmVhXShodHRwczovL3d3dzIuY2Vuc3VzLmdvdi9nZW8vcGRmcy9lZHVjYXRpb24vYnJvY2h1cmVzL1pDVEFzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkIDxicj4gLS0gUG9zdGFsIFppcCBjb2RlcyBhcmUgY29udmVydGVkIGludG8gImdlbmVyYWxpemVkIGFyZWFsIHJlcHJlc2VudGF0aW9ucyIgdGhhdCBhcmUgbm9uLW92ZXJsYXBwaW5nICA8YnI+IC0tIERhdGEgZnJvbSB0aGUgMjAxMCBDZW5zdXMgIAoqKnpjdGFfYXJlYSoqIHwgTGFuZCBhcmVhIG9mIHRoZSB6aXAgY29kZSBhcmVhIGluIG1ldGVycyBzcXVhcmVkICA8YnI+IC0tIERhdGEgZnJvbSB0aGUgMjAxMCBDZW5zdXMgIAoqKnpjdGFfcG9wKiogfCBQb3B1bGF0aW9uIGluIHRoZSB6aXAgY29kZSBhcmVhICA8YnI+IC0tIERhdGEgZnJvbSB0aGUgMjAxMCBDZW5zdXMgIAoqKmltcF9hNTAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIDxicj4gLS0gSW1wZXJ2aW91cyBzdXJmYWNlIGFyZSByb2FkcywgY29uY3JldGUsIHBhcmtpbmcgbG90cywgYnVpbGRpbmdzIDxicj4gLS0gVGhpcyBpcyBhIG1lYXN1cmUgb2YgZGV2ZWxvcG1lbnQgCioqaW1wX2ExMDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IKKippbXBfYTUwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAgCioqaW1wX2ExMDAwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSAgV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAgIAoqKmltcF9hMTUwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgIAoqKmNvdW50eV9hcmVhKiogfCBMYW5kIGFyZWEgb2YgdGhlIGNvdW50eSBvZiB0aGUgbW9uaXRvciBpbiBtZXRlcnMgc3F1YXJlZCAgCioqY291bnR5X3BvcCoqIHwgUG9wdWxhdGlvbiBvZiB0aGUgY291bnR5IG9mIHRoZSBtb25pdG9yICAKKipMb2dfZGlzdF90b19wcmlzZWMqKiB8IExvZyAoTmF0dXJhbCBsb2cpIGRpc3RhbmNlIHRvIGEgcHJpbWFyeSBvciBzZWNvbmRhcnkgcm9hZCBmcm9tIHRoZSBtb25pdG9yIDxicj4gLS0gSGlnaHdheSBvciBtYWpvciByb2FkICAKKipsb2dfcHJpX2xlbmd0aF81MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpIDxicj4gLS0gSGlnaHdheXMgb25seSAgCioqbG9nX3ByaV9sZW5ndGhfMTAwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpIDxicj4gLS0gSGlnaHdheXMgb25seSAgCioqbG9nX3ByaV9sZW5ndGhfMTUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpIDxicj4gLS0gSGlnaHdheXMgb25seSAgCioqbG9nX3ByaV9sZW5ndGhfMjUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpIDxicj4gLS0gSGlnaHdheXMgb25seSAgCioqbG9nX3ByaXNlY19sZW5ndGhfNTAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzEwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzEwMDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfMTUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF8yNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgICAgICAKKipsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgIAoqKmxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xNTAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgIAoqKmxvZ19uZWlfMjAwOF9wbTI1X3N1bV8yNTAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgIAoqKmxvZ19uZWlfMjAwOF9wbTEwX3N1bV8xMDAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgICAKKipsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTUwMDAqKnwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgICAKKipsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMjUwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAgCioqcG9wZGVuc19jb3VudHkqKiB8IFBvcHVsYXRpb24gZGVuc2l0eSAobnVtYmVyIG9mIHBlb3BsZSBwZXIga2lsb21ldGVyIHNxdWFyZWQgYXJlYSBvZiB0aGUgY291bnR5KQoqKnBvcGRlbnNfemN0YSoqIHwgUG9wdWxhdGlvbiBkZW5zaXR5IChudW1iZXIgb2YgcGVvcGxlIHBlciBraWxvbWV0ZXIgc3F1YXJlZCBhcmVhIG9mIHpjdGEpCioqbm9ocyoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIGlzIHRoYXQgKipkbyBub3QgaGF2ZSBhIGhpZ2ggc2Nob29sIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMKKipzb21laHMqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyAqKnNvbWUgaGlnaCBzY2hvb2wgZWR1Y2F0aW9uKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cwoqKmhzKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgY29tcGxldGluZyBhICoqaGlnaCBzY2hvb2wgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAgCioqc29tZWNvbGxlZ2UqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBjb21wbGV0aW5nICoqc29tZSBjb2xsZWdlIGVkdWNhdGlvbioqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgCioqYXNzb2NpYXRlKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgY29tcGxldGluZyBhbiAqKmFzc29jaWF0ZSBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIAoqKmJhY2hlbG9yKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgYSAqKmJhY2hlbG9yJ3MgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAKKipncmFkKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgYSAqKmdyYWR1YXRlIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgCioqcG92KiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3IgaXMgdGhhdCBsaXZlZCBpbiBbKipwb3ZlcnR5KipdKGh0dHBzOi8vYXNwZS5oaHMuZ292LzIwMDgtaGhzLXBvdmVydHktZ3VpZGVsaW5lcykgaW4gMjAwOCAtIG9yIHdvdWxkIGl0IGhhdmUgYmVlbiAyMDA3IGd1aWRlbGluZXM/P2h0dHBzOi8vYXNwZS5oaHMuZ292LzIwMDctaGhzLXBvdmVydHktZ3VpZGVsaW5lcyA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzICAKKipoc19vcmxlc3MqKiB8ICBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgYSAqKmhpZ2ggc2Nob29sIGRlZ3JlZSBvciBsZXNzKiogKHN1bSBvZiBub2hzLCBzb21laHMsIGFuZCBocykgIAoqKnVyYzIwMTMqKiB8IFsyMDEzIFVyYmFuLXJ1cmFsIGNsYXNzaWZpY2F0aW9uXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvZGF0YS9zZXJpZXMvc3JfMDIvc3IwMl8xNjYucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIDYgY2F0ZWdvcnkgdmFyaWFibGUgLSAxIGlzIHRvdGFsbHkgdXJiYW4gNiBpcyBjb21wbGV0ZWx5IHJ1cmFsIDxicj4gIC0tIERhdGEgZnJvbSB0aGUgW05hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3NdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0gICAgIAoqKnVyYzIwMDYqKiB8IFsyMDA2IFVyYmFuLXJ1cmFsIGNsYXNzaWZpY2F0aW9uXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvZGF0YS9zZXJpZXMvc3JfMDIvc3IwMl8xNTQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIDYgY2F0ZWdvcnkgdmFyaWFibGUgLSAxIGlzIHRvdGFsbHkgdXJiYW4gNiBpcyBjb21wbGV0ZWx5IHJ1cmFsIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBbTmF0aW9uYWwgQ2VudGVyIGZvciBIZWFsdGggU3RhdGlzdGljc10oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2luZGV4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgCioqYW9kKiogfCBBZXJvc29sIE9wdGljYWwgRGVwdGggbWVhc3VyZW1lbnQgZnJvbSBhIE5BU0Egc2F0ZWxsaXRlIDxicj4gLS0gYmFzZWQgb24gdGhlIGRpZmZyYWN0aW9uIG9mIGEgbGFzZXIgPGJyPiAtLSB1c2VkIGFzIGEgcHJveHkgb2YgcGFydGljdWxhdGUgcG9sbHV0aW9uIDxicj4gLS0gdW5pdC1sZXNzIC0gaGlnaGVyIHZhbHVlIGluZGljYXRlcyBtb3JlIHBvbGx1dGlvbiA8YnI+IC0tIERhdGEgZnJvbSBOQVNBICAKCjwvZGV0YWlscz4KCk1hbnkgb2YgdGhlc2UgZmVhdHVyZXMgaGF2ZSB0byBkbyB3aXRoIHRoZSBjaXJjdWxhciBhcmVhIGFyb3VuZCB0aGUgbW9uaXRvciBjYWxsZWQgdGhlICJidWZmZXIiLiBUaGVzZSBhcmUgaWxsdXN0cmF0ZWQgaW4gdGhlIGZvbGxvd2luZyBmaWd1cmU6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiODAwcHgiLH0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInJlZ3Jlc3Npb24ucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8xNTI5MjkwNil7dGFyZ2V0PSJfYmxhbmsifQoKCgojICoqRGF0YSBJbXBvcnQqKgoqKioKCkFsbCBvZiBvdXIgZGF0YSB3YXMgcHJldmlvdXNseSBjb2xsZWN0ZWQgYnkgYSBbcmVzZWFyY2hlcl0oaHR0cDovL3d3dy5iaW9zdGF0Lmpoc3BoLmVkdS9+cnBlbmcvKSBhdCB0aGUgW0pvaG5zIEhvcGtpbnMgU2Nob29sIG9mIFB1YmxpYyBIZWFsdGhdKGh0dHBzOi8vd3d3Lmpoc3BoLmVkdS8pIHdobyBzdHVkaWVzIGFpciBwb2xsdXRpb24gYW5kIGNsaW1hdGUgY2hhbmdlLiAKCldlIGhhdmUgb25lIENTViBmaWxlIHRoYXQgY29udGFpbnMgYm90aCBvdXIgc2luZ2xlICoqb3V0Y29tZSB2YXJpYWJsZSoqIGFuZCBhbGwgb2Ygb3VyICoqZmVhdHVyZXMqKiAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykuCgpOZXh0LCB3ZSBpbXBvcnQgb3VyIGRhdGEgaW50byBSIG5vdyBzbyB0aGF0IHdlIGNhbiBleHBsb3JlIHRoZSBkYXRhIGZ1cnRoZXIuIApXZSB3aWxsIGNhbGwgb3VyIGRhdGEgb2JqZWN0IGBwbWAgZm9yIHBhcnRpY3VsYXRlIG1hdHRlci4gCldlIGltcG9ydCB0aGUgZGF0YSB1c2luZyB0aGUgYHJlYWRfY3N2KClgIGZ1bmN0aW9uIGZyb20gdGhlIGByZWFkcmAgcGFja2FnZS4gCmBgYHtyfQpwbSA8LSByZWFkcjo6cmVhZF9jc3YoaGVyZSgiZG9jcyIsICJwbTI1X2RhdGEuY3N2IikpCmBgYAoKCgojICoqRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nKioKKioqCgpUaGUgZmlyc3Qgc3RlcCBpbiBwZXJmb3JtaW5nIGFueSBkYXRhIGFuYWx5c2lzIGlzIHRvIGV4cGxvcmUgdGhlIGRhdGEuIAoKRm9yIGV4YW1wbGUsIHdlIG1pZ2h0IHdhbnQgdG8gYmV0dGVyIHVuZGVyc3RhbmQgdGhlIHZhcmlhYmxlcyBpbmNsdWRlZCBpbiB0aGUgZGF0YSwgYXMgd2UgbWF5IGxlYXJuIGFib3V0IGltcG9ydGFudCBkZXRhaWxzIGFib3V0IHRoZSBkYXRhIHRoYXQgd2Ugc2hvdWxkIGtlZXAgaW4gbWluZCBhcyB3ZSB0cnkgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZS4KCkZpcnN0LCBsZXQncyBqdXN0IGdldCBhIGdlbmVyYWwgc2Vuc2Ugb2Ygb3VyIGRhdGEuIApXZSBjYW4gZG8gdGhhdCB1c2luZyB0aGUgYGdsaW1wc2UoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSAoaXQgaXMgYWxzbyBpbiB0aGUgYHRpYmJsZWAgcGFja2FnZSkuCgpXZSB3aWxsIGFsc28gdXNlIHRoZSBgJT4lYCBwaXBlLCB3aGljaCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgdGhlIGlucHV0IGZvciBsYXRlciBzZXF1ZW50aWFsIHN0ZXBzLiAKClRoaXMgd2lsbCBtYWtlIG1vcmUgc2Vuc2Ugd2hlbiB3ZSBoYXZlIG11bHRpcGxlIHNlcXVlbnRpYWwgc3RlcHMgdXNpbmcgdGhlIHNhbWUgZGF0YSBvYmplY3QuIAoKVG8gdXNlIHRoZSBwaXBlIG5vdGF0aW9uIHdlIG5lZWQgdG8gaW5zdGFsbCBhbmQgbG9hZCBgZHBseXJgIGFzIHdlbGwuCgpGb3IgZXhhbXBsZSwgaGVyZSB3ZSBzdGFydCB3aXRoIGBwbWAgZGF0YSBvYmplY3QgYW5kICJwaXBlIiB0aGUgb2JqZWN0IGludG8gYXMgaW5wdXQgaW50byB0aGUgYGdsaW1wc2UoKWAgZnVuY3Rpb24uIApUaGUgb3V0cHV0IGlzIGlzIGFuIG92ZXJ2aWV3IG9mIHdoYXQgaXMgaW4gdGhlIGBwbWAgb2JqZWN0IHN1Y2ggYXMgdGhlIG51bWJlciBvZiByb3dzIGFuZCBjb2x1bW5zLCBhbGwgdGhlIGNvbHVtbiBuYW1lcywgdGhlIGRhdGEgdHlwZXMgZm9yIGVhY2ggY29sdW1uIGFuZCB0aGUgZmlyc3QgdmlldyB2YWx1ZXMgaW4gZWFjaCBjb2x1bW4uIApUaGUgb3V0cHV0IGJlbG93IGlzIHNjcm9sbGFibGUgc28geW91IGNhbiBzZWUgZXZlcnl0aGluZyBmcm9tIHRoZSBgZ2xpbXBzZSgpYCBmdW5jdGlvbi4gCgojIyMjIHsuc2Nyb2xsYWJsZSB9CgpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpwbSAlPiUKICBkcGx5cjo6Z2xpbXBzZSgpCmBgYAoKIyMjIwoKV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSA4NzYgbW9uaXRvcnMgKHJvd3MpIGFuZCB0aGF0IHdlIGhhdmUgNTAgdG90YWwgdmFyaWFibGVzIChjb2x1bW5zKSAtIG9uZSBvZiB3aGljaCBpcyB0aGUgb3V0Y29tZSB2YXJpYWJsZS4gSW4gdGhpcyBjYXNlLCB0aGUgb3V0Y29tZSB2YXJpYWJsZSBpcyBjYWxsZWQgYHZhbHVlYC4gCgpOb3RpY2UgdGhhdCBzb21lIG9mIHRoZSB2YXJpYWJsZXMgdGhhdCB3ZSB3b3VsZCB0aGluayBvZiBhcyBmYWN0b3JzIChvciBjYXRlZ29yaWNhbCBkYXRhKSBhcmUgY3VycmVudGx5IG9mIGNsYXNzIGNoYXJhY3RlciBhcyBpbmRpY2F0ZWQgYnkgdGhlIGA8Y2hyPmAganVzdCB0byB0aGUgcmlnaHQgb2YgdGhlIGNvbHVtbiBuYW1lcy92YXJpYWJsZSBuYW1lcyBpbiB0aGUgYGdsaW1wc2UoKWAgb3V0cHV0LiBUaGlzIG1lYW5zIHRoYXQgdGhlIHZhcmlhYmxlIHZhbHVlcyBhcmUgY2hhcmFjdGVyIHN0cmluZ3MsIHN1Y2ggYXMgd29yZHMgb3IgcGhyYXNlcy4gCgpUaGUgb3RoZXIgdmFyaWFibGVzIGFyZSBvZiBjbGFzcyBgPGRibD5gLCB3aGljaCBzdGFuZHMgZm9yIGRvdWJsZSBwcmVjaXNpb24gd2hpY2ggaW5kaWNhdGVzIHRoYXQgdGhlIGFyZSBudW1lcmljIGFuZCB0aGF0IHRoZXkgaGF2ZSBkZWNpbWFsIHZhbHVlcy4gSW4gY29udHJhc3QsIG9uZSBjb3VsZCBoYXZlIGludGVnZXIgdmFsdWVzIHdoaWNoIHdvdWxkIG5vdCBhbGxvdyBmb3IgZGVjaW1hbCBudW1iZXJzLiBIZXJlIGlzIGEgW2xpbmtdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RvdWJsZS1wcmVjaXNpb25fZmxvYXRpbmctcG9pbnRfZm9ybWF0KXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIGRvdWJsZSBwcmVjaXNpb24gbnVtZXJpYyB2YWx1ZXMuCgpBbm90aGVyIGNvbW1vbiBkYXRhIGNsYXNzIGlzIGZhY3RvciB3aGljaCBpcyBhYmJyZXZpYXRlZCBsaWtlIHRoaXM6IGA8ZmN0PmAuIEEgZmFjdG9yIGlzIHNvbWV0aGluZyB0aGF0IGhhcyB1bmlxdWUgbGV2ZWxzIGJ1dCB0aGVyZSBpcyBubyBhcHByZWNpYWJsZSBvcmRlciB0byB0aGUgbGV2ZWxzLiBGb3IgZXhhbXBsZSB3ZSBjYW4gaGF2ZSBhIG51bWVyaWMgdmFsdWUgdGhhdCBpcyBqdXN0IGFuIGlkIHRoYXQgd2Ugd2FudCB0byBiZSBpbnRlcnByZXRlZCBhcyBqdXN0IGEgdW5pcXVlIGxldmVsIGFuZCBub3QgYXMgdGhlIG51bWJlciB0aGF0IGl0IHdvdWxkIHR5cGljYWxseSBpbmRpY2F0ZS4gVGhpcyB3b3VsZCBiZSB1c2VmdWwgZm9yIHNldmVyYWwgb2Ygb3VyIHZhcmlhYmxlczoKCjEuIHRoZSBtb25pdG9yIElEIChgaWRgKQoyLiB0aGUgRmVkZXJhbCBJbmZvcm1hdGlvbiBQcm9jZXNzaW5nIFN0YW5kYXJkIG51bWJlciBmb3IgdGhlIGNvdW50eSB3aGVyZSB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCAoYGZpcHNgKQozLiB0aGUgemlwIGNvZGUgdGFidWxhdGlvbiBhcmVhIChgemN0YWApCgpOb25lIG9mIHRoZSB2YWx1ZXMgYWN0dWFsbHkgaGF2ZSBhbnkgcmVhbCBudW1lcmljIG1lYW5pbmcsIHNvIHdlIHdhbnQgdG8gbWFrZSBzdXJlIHRoYXQgUiBkb2VzIG5vdCBpbnRlcnByZXQgdGhlbSBhcyBpZiB0aGV5IGRvLiAKClNvIGxldCdzIGNvbnZlcnQgdGhlc2UgdmFyaWFibGVzIGludG8gZmFjdG9ycy4gCldlIGNhbiBkbyB0aGlzIHVzaW5nIHRoZSBgYWNyb3NzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgYW5kIHRoZSBgYXMuZmFjdG9yKClgIGJhc2UgZnVuY3Rpb24uIApUaGUgYGFjcm9zcygpYCBmdW5jdGlvbiBoYXMgdHdvIG1haW4gYXJndW1lbnRzOiAoaSkgdGhlIGNvbHVtbnMgeW91IHdhbnQgdG8gb3BlcmF0ZSBvbiBhbmQgKGlpKSB0aGUgZnVuY3Rpb24gb3IgbGlzdCBvZiBmdW5jdGlvbnMgdG8gYXBwbHkgdG8gZWFjaCBjb2x1bW4uIAoKSW4gdGhpcyBjYXNlLCB3ZSBhcmUgYWxzbyB1c2luZyB0aGUgYG1hZ3JpdHRyYCBhc3NpZ25tZW50IHBpcGUgb3IgZG91YmxlIHBpcGUgdGhhdCBsb29rcyBsaWtlIHRoaXMgYCU8PiVgIG9mIHRoZSBgbWFncml0dHJgIHBhY2thZ2UuIApUaGlzIGFsbG93cyB1cyB1c2UgdGhlIGBwbWAgZGF0YSBhcyBpbnB1dCwgYnV0IGFsc28gcmVhc3NpZ25zIHRoZSBvdXRwdXQgdG8gdGhlIHNhbWUgZGF0YSBvYmplY3QgbmFtZS4KCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCnBtICU8PiUKICBtdXRhdGUoYWNyb3NzKGMoaWQsIGZpcHMsIHpjdGEpLCBhcy5mYWN0b3IpKSAKCmdsaW1wc2UocG0pCmBgYAoKIyMjIwoKR3JlYXQhIE5vdyB3ZSBjYW4gc2VlIHRoYXQgdGhlc2UgdmFyaWFibGVzIGFyZSBub3cgZmFjdG9ycyBhcyBpbmRpY2F0ZWQgYnkgYDxmY3Q+YCBhZnRlciB0aGUgdmFyaWFibGUgbmFtZS4KCgoKIyMjIFNraW0gcGFja2FnZQoKVGhlIGBza2ltKClgIGZ1bmN0aW9uIG9mIHRoZSBgc2tpbXJgIHBhY2thZ2UgaXMgYWxzbyByZWFsbHkgaGVscGZ1bCBmb3IgZ2V0dGluZyBhIGdlbmVyYWwgc2Vuc2Ugb2YgeW91ciBkYXRhLgpCeSBkZXNpZ24sIGl0IHByb3ZpZGVzIHN1bW1hcnkgc3RhdGlzdGljcyBhYm91dCB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgc2V0LiAKCgojIyMjIHsuc2Nyb2xsYWJsZSB9CgpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpza2ltcjo6c2tpbShwbSkKYGBgCgojIyMjCgpOb3RpY2UgaG93IHRoZXJlIGlzIGEgY29sdW1uIGNhbGxlZCBgbl9taXNzaW5nYCBhYm91dCB0aGUgbnVtYmVyIG9mIHZhbHVlcyB0aGF0IGFyZSBtaXNzaW5nLiAKClRoaXMgaXMgYWxzbyBpbmRpY2F0ZWQgYnkgdGhlIGBjb21wbGV0ZV9yYXRlYCB2YXJpYWJsZSAob3IgbWlzc2luZy9udW1iZXIgb2Ygb2JzZXJ2YXRpb25zKS4gCgpJbiBvdXIgZGF0YSBzZXQsIGl0IGxvb2tzIGxpa2Ugb3VyIGRhdGEgZG8gbm90IGNvbnRhaW4gYW55IG1pc3NpbmcgZGF0YS4gCgpBbHNvIG5vdGljZSBob3cgdGhlIGZ1bmN0aW9uIHByb3ZpZGVzIHNlcGFyYXRlIHRhYmxlcyBvZiBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIGVhY2ggZGF0YSB0eXBlOiBjaGFyYWN0ZXIsIGZhY3RvciBhbmQgbnVtZXJpYy4gCgpOZXh0LCB0aGUgYG5fdW5xaXVlYCBjb2x1bW4gc2hvd3MgdXMgdGhlIG51bWJlciBvZiB1bmlxdWUgdmFsdWVzIGZvciBlYWNoIG9mIG91ciBjb2x1bW5zLiAKV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSA0OSBzdGF0ZXMgcmVwcmVzZW50ZWQgaW4gdGhlIGRhdGEuCgpXZSBjYW4gc2VlIHRoYXQgZm9yIG1hbnkgdmFyaWFibGVzIHRoZXJlIGFyZSBtYW55IGxvdyB2YWx1ZXMgYXMgdGhlIGRpc3RyaWJ1dGlvbiBzaG93cyB0d28gcGVha3MsIG9uZSBuZWFyIHplcm8gYW5kIGFub3RoZXIgd2l0aCBhIGhpZ2hlciB2YWx1ZS4gCgpUaGlzIGlzIHRydWUgZm9yIHRoZSBgaW1wYCB2YXJpYWJsZXMgKG1lYXN1cmVzIG9mIGRldmVsb3BtZW50KSwgdGhlIGBuZWlgIHZhcmlhYmxlcyAobWVhc3VyZXMgb2YgZW1pc3Npb24gc291cmNlcykgYW5kIHRoZSByb2FkIGRlbnNpdHkgdmFyaWFibGVzLiAKCldlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZSByYW5nZSBvZiBzb21lIG9mIHRoZSB2YXJpYWJsZXMgaXMgdmVyeSBsYXJnZSwgaW4gcGFydGljdWxhciB0aGUgYXJlYSBhbmQgcG9wdWxhdGlvbiByZWxhdGVkIHZhcmlhYmxlcy4KCgpMZXQncyB0YWtlIGEgbG9vayB0byBzZWUgd2hpY2ggc3RhdGVzIGFyZSBpbmNsdWRlZCB1c2luZyB0aGUgYGRpc3RpbmN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2U6CgpgYGB7ciwgZXZhbCA9IEZBTFNFfSAKcG0gJT4lIAogIGRwbHlyOjpkaXN0aW5jdChzdGF0ZSkgCmBgYAoKClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6CgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyLCBlY2hvID0gRkFMU0V9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKcG0gJT4lIAogIGRpc3RpbmN0KHN0YXRlKSAlPiUKIyB0aGlzIGFsbG93cyB1cyB0byBzaG93IHRoZSBmdWxsIG91dHB1dCBpbiB0aGUgcmVuZGVyZWQgcm1hcmtkb3duCiBwcmludChuID0gMWUzKQpgYGAKIyMjIwoKSXQgbG9va3MgbGlrZSAiRGlzdHJpY3Qgb2YgQ29sdW1iaWEiIGlzIGJlaW5nIGluY2x1ZGVkIGFzIGEgc3RhdGUuIApXZSBjYW4gc2VlIHRoYXQgQWxhc2thIGFuZCBIYXdhaWkgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgZGF0YS4KCkxldCdzIGFsc28gdGFrZSBhIGxvb2sgdG8gc2VlIGhvdyBtYW55IG1vbml0b3JzIHRoZXJlIGFyZSBpbiBhIGZldyBjaXRpZXMuIFdlIGNhbiB1c2UgdGhlIGBmaWx0ZXIoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBkbyBzby4gRm9yIGV4YW1wbGUsIGxldCdzIGxvb2sgYXQgQWxidXF1ZXJxdWUsIE5ldyBNZXhpY28uIAoKYGBge3J9CnBtICU+JSBkcGx5cjo6ZmlsdGVyKGNpdHkgPT0gIkFsYnVxdWVycXVlIikKCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZXJlIHdlcmUgb25seSB0d28gbW9uaXRvcnMgaW4gdGhlIGNpdHkgb2YgQWxidXF1ZXJxdWUgaW4gMjAwNi4gTGV0J3MgY29tcGFyZSB0aGlzIHdpdGggQmFsdGltb3JlLgoKYGBge3J9CnBtICU+JSBkcGx5cjo6ZmlsdGVyKGNpdHkgPT0gIkJhbHRpbW9yZSIpCgpgYGAKClRoZXJlIHdlcmUgaW4gY29udHJhc3QgZml2ZSBtb25pdG9ycyBmb3IgdGhlIGNpdHkgb2YgQmFsdGltb3JlLCBkZXNwaXRlIHRoZSBmYWN0IHRoYXQgaWYgd2UgdGFrZSBhIGxvb2sgYXQgdGhlIGxhbmQgYXJlYSBhbmQgcG9wdWxhdGlvbiBvZiB0aGUgY291bnRpZXMgZm9yIEJsYXRpbW9yZSBDaXR5IGFuZCBBbGJ1cXVlcnF1ZSwgd2UgY2FuIHNlZSB0aGF0IHRoZXkgaGFkIHZlcnkgc2ltaWxhciBsYW5kIGFyZWEgYW5kIHBvcHVsYXRpb25zLgoKYGBge3J9CnBtICU+JSAKICBkcGx5cjo6ZmlsdGVyKGNpdHkgPT0gIkJhbHRpbW9yZSIpICU+JSAKICBzZWxlY3QoY291bnR5X2FyZWE6Y291bnR5X3BvcCkKcG0gJT4lIAogIGRwbHlyOjpmaWx0ZXIoY2l0eSA9PSAiQWxidXF1ZXJxdWUiKSAlPiUKICBzZWxlY3QoY291bnR5X2FyZWE6Y291bnR5X3BvcCkKCmBgYAoKSW4gZmFjdCwgdGhlIGNvdW50eSBjb250YWluaW5nIEFsYnVlcnF1ZSBoYWQgYSBsYXJnZXIgcG9wdWxhdGlvbi4gVGh1cyB0aGUgbWVhc3VyZW1lbnRzIGZvciBBbGJ1cXVlcnF1ZSB3ZXJlIG5vdCBhcyB0aG9yb3VnaCBhcyB0aGV5IHdlcmUgZm9yIEJhbHRpbW9yZS4KClRoaXMgbWF5IGJlIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZSBtb25pdG9yIHZhbHVlcyB3ZXJlIGxvd2VyIGluIEFsYnVxdWVycXVlLiBJdCBpcyBpbnRlcmVzdGluZyB0byBub3RlIGhlcmUgdGhhdCB0aGUgQ01BUSB2YWx1ZXMgYXJlIHF1aXRlIHNpbWlsYXIgZm9yIGJvdGggY2l0aWVzLgoKCiMjIEV2YWx1YXRlIGNvcnJlbGF0aW9uCgpJbiBwcmVkaWN0aW9uIGFuYWx5c2VzLCBpdCBpcyBhbHNvIHVzZWZ1bCB0byBldmFsdWF0ZSBpZiBhbnkgb2YgdGhlIHZhcmlhYmxlcyBhcmUgY29ycmVsYXRlZC4gV2h5IHNob3VsZCB3ZSBjYXJlIGFib3V0IHRoaXM/CgpJZiB3ZSBhcmUgdXNpbmcgYSBsaW5lYXIgcmVncmVzc2lvbiB0byBtb2RlbCBvdXIgZGF0YSB0aGVuIHdlIG1pZ2h0IHJ1biBpbnRvIGEgcHJvYmxlbSBjYWxsZWQgbXVsdGljb2xpbmVhcml0eSB3aGljaCBjYW4gbGVhZCB1cyB0byBtaXNpbnRlcnByZXQgd2hhdCBpcyByZWFsbHkgcHJlZGljdGl2ZSBvZiBvdXIgb3V0Y29tZSB2YXJpYWJsZS4gVGhpcyBwaGVub21lbm9uIG9jY3VycyB3aGVuIHRoZSBwcmVkaWN0b3IgdmFyaWFibGVzIGFjdHVhbGx5IHByZWRpY3Qgb25lIGFub3RoZXIuIFNlZSBbdGhpcyBjYXNlIHN0dWR5XShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vb2NzLWJwLVJUQy1hbmFseXNpcy8pIGZvciBhIGRlZXBlciBleHBsYW5hdGlvbiBhYm91dCB0aGlzLiAKCkFub3RoZXIgcmVhc29uIHdlIHNob3VsZCBsb29rIG91dCBmb3IgY29ycmVsYXRpb24gaXMgdGhhdCB3ZSBkb24ndCB3YW50IHRvIGluY2x1ZGUgcmVkdW5kYW50IHZhcmlhYmxlcy4gVGhpcyBjYW4gYWRkIHVubmVjZXNzYXJ5IG5vaXNlIHRvIG91ciBhbGdvcml0aG0gY2F1c2luZyBhIHJlZHVjdGlvbiBpbiBwcmVkaWN0aW9uIGFjY3VyYWN5IGFuZCBpdCBjYW4gY2F1c2Ugb3VyIGFsZ29yaXRobSB0byBiZSB1bm5lY2Vzc2FyaWx5IHNsb3dlci4gRmluYWxseSwgaXQgY2FuIGFsc28gbWFrZSBpdCBkaWZmaWN1bHQgdG8gaW50ZXJwcmV0IHdoYXQgdmFyaWFibGVzIGFyZSBhY3R1YWxseSBwcmVkaWN0aXZlLgoKSW50dWl0aXZlbHkgd2UgY2FuIGV4cGVjdCBzb21lIG9mIG91ciB2YXJpYWJsZXMgdG8gYmUgY29ycmVsYXRlZC4KCkxldCdzIGZpcnN0IHRha2UgYSBsb29rIGF0IGFsbCBvZiBvdXIgbnVtZXJpYyB2YXJpYWJsZXMgd2l0aCB0aGVgY29ycnBsb3RgIHBhY2thZ2U6ClRoZSBgY29ycnBsb3RgIHBhY2thZ2UgaXMgYW5vdGhlciBvcHRpb24gdG8gbG9vayBhdCBjb3JyZWxhdGlvbiBhbW9uZyBwb3NzaWJsZSBwcmVkaWN0b3JzLCBhbmQgcGFydGljdWxhcmx5IHVzZWZ1bCBpZiB3ZSBoYXZlIG1hbnkgcHJlZGljdG9ycy4gCgpGaXJzdCwgd2UgY2FsY3VsYXRlIHRoZSBQZWFyc29uIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyBiZXR3ZWVuIGFsbCBmZWF0dXJlcyBwYWlyd2lzZSB1c2luZyB0aGUgYGNvcigpYCBmdW5jdGlvbiBvZiB0aGUgYHN0YXRzYCBwYWNrYWdlICh3aGljaCBpcyBsb2FkZWQgYXV0b21hdGljYWxseSkuIFRoZW4gd2UgdXNlIHRoZSBgY29ycnBsb3Q6OmNvcnJwbG90KClgIGZ1bmN0aW9uLiAKCmBgYHtyfQpQTV9jb3IgPC0gY29yKHBtICU+JSBkcGx5cjo6c2VsZWN0X2lmKGlzLm51bWVyaWMpKQpjb3JycGxvdDo6Y29ycnBsb3QoUE1fY29yLCB0bC5jZXggPSAwLjUpCmBgYApUaGUgYHRsLmNleCA9IDAuNWAgYXJndW1lbnQgY29udHJvbHMgdGhlIHNpemUgb2YgdGhlIHRleHQgbGFiZWwuIAoKV2UgY2FuIGFsc28gcGxvdCB0aGUgYWJzb2x1dGUgdmFsdWUgb2YgdGhlIFBlYXJzb24gY29ycmVsYXRpb24gY29lZmZpY2llbnRzIHVzaW5nIHRoZSBgYWJzKClgIGZ1bmN0aW9uIGZyb20gYmFzZSBSIGFuZCBjaGFuZ2UgdGhlIG9yZGVyIG9mIHRoZSBjb2x1bW5zLiAgCmBgYHtyfQpjb3JycGxvdChhYnMoUE1fY29yKSwgb3JkZXIgPSAiaGNsdXN0IiwgdGwuY2V4ID0gMC41LCBjbC5saW0gPSBjKDAsIDEpKQoKYGBgCgpUaGVyZSBhcmUgc2V2ZXJhbCBvcHRpb25zIGZvciBvcmRlcmluZyB0aGUgdmFyaWFibGVzLiBTZWUgW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jb3JycGxvdC92aWduZXR0ZXMvY29ycnBsb3QtaW50cm8uaHRtbCkgZm9yIG1vcmUgb3B0aW9ucy4gSGVyZSB3ZSB3aWxsIHVzZSB0aGUgImhjbHVzdCIgb3B0aW9uIGZvciBvcmRlcmluZyBieSBbaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmddKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0hpZXJhcmNoaWNhbF9jbHVzdGVyaW5nKSAtIHdoaWNoIHdpbGwgb3JkZXIgdGhlIHZhcmlhYmxlcyBieSBob3cgc2ltaWxhciB0aGV5IGFyZSB0byBvbmUgYW5vdGhlci4KClRoZSBgY2wubGltID0gYygwLCAxKWAgYXJndW1lbnQgbGltaXRzIHRoZSBjb2xvciBsYWJlbCB0byBiZSBiZXR3ZWVuIDAgYW5kIDEuIAoKCldlIGNhbiBzZWUgdGhhdCB0aGUgZGV2ZWxvcG1lbnQgdmFyaWFibGVzIChgaW1wYCkgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlciBhcyB3ZSBtaWdodCBleHBlY3QuIApXZSBhbHNvIHNlZSB0aGF0IHRoZSByb2FkIGRlbnNpdHkgdmFyaWFibGVzIHNlZW0gdG8gYmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIsIGFuZCB0aGUgZW1pc3Npb24gdmFyaWFibGVzIHNlZW0gdG8gYmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIuIAoKCkFsc28gbm90aWNlIHRoYXQgbm9uZSBvZiB0aGUgcHJlZGljdG9ycyBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBvdXIgb3V0Y29tZSB2YXJpYWJsZSAoYHZhbHVlYCkuCgpXZSBjYW4gdGFrZSBhbHNvIHRha2UgYSBjbG9zZXIgbG9vayAgdXNpbmcgdGhlIGBnZ2NvcnIoKWAgZnVuY3Rpb24gYW5kIHRoZSBgZ2dwYWlycygpYCBmdW5jdGlvbiBvZiB0aGUgYEdHYWxseWAgcGFja2FnZS4gCgpUbyBzZWxlY3Qgb3VyIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCB3ZSBjYW4gdXNlIHRoZSBgc2VsZWN0KClgIGZ1bmN0aW9uIHdpdGggdGhlIGBjb250YWlucygpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlLiAKCkZpcnN0IGxldCdzIGxvb2sgYXQgdGhlIGBpbXBgL2RldmVsb3BtZW50IHZhcmlhYmxlcy4gCldlIGNhbiBjaGFuZ2UgdGhlIGRlZmF1bHQgY29sb3IgcGFsZXR0ZSAoYHBhbGV0dGUgPSAiUmRCdSJgKSBhbmQgYWRkIG9uIApjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgdG8gdGhlIHBsb3QgKGBsYWJlbCA9IFRSVUVgKS4KCmBgYHtyLCBvdXQud2lkdGggPSAiNDAwcHgifQpzZWxlY3QocG0sIGNvbnRhaW5zKCJpbXAiKSkgJT4lCiAgZ2djb3JyKHBhbGV0dGUgPSAiUmRCdSIsIGxhYmVsID0gVFJVRSkKCnNlbGVjdChwbSwgY29udGFpbnMoImltcCIpKSAlPiUKICBnZ3BhaXJzKCkKYGBgCgoKCkluZGVlZCwgd2UgY2FuIHNlZSB0aGF0IGBpbXBfYTEwMDBgIGFuZCBgaW1wX2E1MDBgIGFyZSBoaWdobHkgY29ycmVsYXRlZCwgYXMgd2VsbCBhcyBgaW1wX2ExMDAwMGAsIGBpbXBfYTE1MDAwYC4KCk5leHQsIGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSByb2FkIGRlbnNpdHkgZGF0YToKCmBgYHtyLCBmaWcud2VpZ2h0PTEyfQpzZWxlY3QocG0sIGNvbnRhaW5zKCJwcmkiKSkgJT4lCiAgZ2djb3JyKHBhbGV0dGUgPSAiUmRCdSIsIGhqdXN0ID0gLjg1LCBzaXplID0gMywKICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQpgYGAKCldlIGNhbiBzZWUgdGhhdCBtYW55IG9mIHRoZSByb2FkIGRlbnNpdHkgdmFyaWFibGVzIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIG9uZSBhbm90aGVyLCB3aGlsZSBvdGhlcnMgYXJlIGxlc3Mgc28uCgpGaW5hbGx5IGxldCdzIGxvb2sgYXQgdGhlIGVtaXNzaW9uIHZhcmlhYmxlcy4KCmBgYHtyfQpzZWxlY3QocG0sIGNvbnRhaW5zKCJuZWkiKSkgJT4lCiAgZ2djb3JyKHBhbGV0dGUgPSAiUmRCdSIsIGhqdXN0ID0gLjg1LCBzaXplID0gMywKICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQoKc2VsZWN0KHBtLCBjb250YWlucygibmVpIikpICU+JQogIGdncGFpcnMoKQpgYGAKCldlIHdvdWxkIGFsc28gZXhwZWN0IHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgZGF0YSBtaWdodCBjb3JyZWxhdGUgd2l0aCBzb21lIG9mIHRoZXNlIHZhcmlhYmxlcy4gCkxldCdzIHRha2UgYSBsb29rLgoKYGBge3J9CnBtICU+JQpzZWxlY3QobG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwLCBwb3BkZW5zX2NvdW50eSwgCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCkgJT4lCiAgZ2djb3JyKHBhbGV0dGUgPSAiUmRCdSIsICBoanVzdCA9IC44NSwgc2l6ZSA9IDMsCiAgICAgICBsYXlvdXQuZXhwPTIsIGxhYmVsID0gVFJVRSkKCnBtICU+JQpzZWxlY3QobG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwLCBwb3BkZW5zX2NvdW50eSwgCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCwgY291bnR5X3BvcCkgJT4lCiAgZ2dwYWlycygpCmBgYAoKCkludGVyZXN0aW5nLCBzbyB0aGVzZSB2YXJpYWJsZXMgZG9uJ3QgYXBwZWFyIHRvIGJlIGhpZ2hseSBjb3JyZWxhdGVkLCB0aGVyZWZvcmUgd2UgbWlnaHQgbmVlZCB2YXJpYWJsZXMgZnJvbSBlYWNoIG9mIHRoZSBjYXRlZ29yaWVzIHRvIHByZWRpY3Qgb3VyIG1vbml0b3IgUE1+Mi41fiBwb2xsdXRpb24gdmFsdWVzLgoKQmVjYXVzZSBzb21lIHZhcmlhYmxlcyBpbiBvdXIgZGF0YSBoYXZlIGV4dHJlbWUgdmFsdWVzLCBpdCBtaWdodCBiZSBnb29kIHRvIHRha2UgYSBsb2cgdHJhbnNmb3JtYXRpb24uIFRoaXMgY2FuIGFmZmVjdCBvdXIgZXN0aW1hdGVzIG9mIGNvcnJlbGF0aW9uLiAKYGBge3J9CnBtICU+JQogIG11dGF0ZShsb2dfcG9wZGVuc19jb3VudHk9IGxvZyhwb3BkZW5zX2NvdW50eSkpICU+JQpzZWxlY3QobG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwLCBsb2dfcG9wZGVuc19jb3VudHksIAogICAgICAgbG9nX3ByaV9sZW5ndGhfMTAwMDAsIGltcF9hMTAwMDApICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCAgaGp1c3QgPSAuODUsIHNpemUgPSAzLAogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpCgpwbSAlPiUKICBtdXRhdGUobG9nX3BvcGRlbnNfY291bnR5PSBsb2cocG9wZGVuc19jb3VudHkpKSAlPiUKICBtdXRhdGUobG9nX3BvcF9jb3VudHkgPSBsb2coY291bnR5X3BvcCkpICU+JQpzZWxlY3QobG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwLCBsb2dfcG9wZGVuc19jb3VudHksIAogICAgICAgbG9nX3ByaV9sZW5ndGhfMTAwMDAsIGltcF9hMTAwMDAsIGxvZ19wb3BfY291bnR5KSAlPiUKICBnZ3BhaXJzKCkKYGBgCgpJbmRlZWQgdGhpcyBpbmNyZWFzZWQgdGhlIGNvcnJlbGF0aW9uLCBidXQgdmFyaWFibGVzIGZyb20gZWFjaCBvZiB0aGVzZSBjYXRlZ29yaWVzIG1heSBzdGlsbCBwcm92ZSB0byBiZSB1c2VmdWwgZm9yIHByZWRpY3Rpb24uCgpOb3cgdGhhdCB3ZSBoYXZlIGEgc2Vuc2Ugb2Ygd2hhdCBvdXIgZGF0YSBhcmUsIHdlIGNhbiBnZXQgc3RhcnRlZCB3aXRoIGJ1aWxkaW5nIGEgbWFjaGluZSBsZWFybmluZyBtb2RlbCB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24uIAoKIyAqKldoYXQgaXMgbWFjaGluZSBsZWFybmluZz8qKiAgeyN3aGF0aXNtbH0KKioqCgpZb3UgbWF5IGhhdmUgbGVhcm5lZCBhYm91dCB0aGUgY2VudHJhbCBkb2dtYSBvZiBzdGF0aXN0aWNzIHRoYXQgeW91IHNhbXBsZSBmcm9tIGEgcG9wdWxhdGlvbi4KCiFbXShpbWcvY2RpMS5wbmcpCgpUaGVuIHlvdSB1c2UgdGhlIHNhbXBsZSB0byB0cnkgdG8gZ3Vlc3Mgd2hhdCBpcyBoYXBwZW5pbmcgaW4gdGhlIHBvcHVsYXRpb24uCgohW10oaW1nL2NkaTIucG5nKQoKRm9yIHByZWRpY3Rpb24gd2UgaGF2ZSBhIHNpbWlsYXIgc2FtcGxpbmcgcHJvYmxlbQoKIVtdKGltZy9jZHAxLnBuZykKCkJ1dCBub3cgd2UgYXJlIHRyeWluZyB0byBidWlsZCBhIHJ1bGUgdGhhdCBjYW4gYmUgdXNlZCB0byBwcmVkaWN0IGEgc2luZ2xlIG9ic2VydmF0aW9uJ3MgdmFsdWUgb2Ygc29tZSBjaGFyYWN0ZXJpc3RpYyB1c2luZyBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIG90aGVyIG9ic2VydmF0aW9ucy4gCgohW10oaW1nL2NkcDIucG5nKQoKTGV0J3MgbWFrZSB0aGlzIG1vcmUgY29uY3JldGUuCgpJZiB5b3UgcmVjYWxsIGZyb20gdGhlIFtXaGF0IGFyZSB0aGUgZGF0YT9dKCN3aGF0YXJldGhlZGF0YSkgc2VjdGlvbiBhYm92ZSwgd2hlbiB3ZSBhcmUgdXNpbmcgbWFjaGluZSBsZWFybmluZyBmb3IgcHJlZGljdGlvbiwgb3VyIGRhdGEgY29uc2lzdHMgb2Y6IAoKMS4gQW4gKipjb250aW51b3VzKiogb3V0Y29tZSB2YXJpYWJsZSB0aGF0IHdlIHdhbnQgdG8gcHJlZGljdCAKMi4gQSBzZXQgb2YgZmVhdHVyZShzKSAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgdGhhdCB3ZSB1c2UgdG8gcHJlZGljdCB0aGUgb3V0Y29tZSB2YXJpYWJsZQoKV2Ugd2lsbCB1c2UgJFkkIHRvIGRlbm90ZSB0aGUgb3V0Y29tZSB2YXJpYWJsZSBhbmQgJFggPSAoWF8xLCBcZG90cywgWF9wKSQgdG8gZGVub3RlICRwJCBkaWZmZXJlbnQgZmVhdHVyZXMgKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpLiAKQmVjYXVzZSBvdXIgb3V0Y29tZSB2YXJpYWJsZSBpcyAqKmNvbnRpbnVvdXMqKiAoYXMgb3Bwb3NlZCB0byBjYXRlZ29yaWNhbCksIHdlIGFyZSBpbnRlcmVzdGVkIGluIGEgcGFydGljdWxhciB0eXBlIG9mIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtLiAKCk91ciBnb2FsIGlzIHRvIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gdGhhdCB1c2VzIHRoZSBmZWF0dXJlcyAkWCQgYXMgaW5wdXQgYW5kIHByZWRpY3RzIGFuIG91dGNvbWUgdmFyaWFibGUgKG9yIGFpciBwb2xsdXRpb24gbGV2ZWxzKSBpbiB0aGUgc2l0dWF0aW9uIHdoZXJlIHdlIGRvIG5vdCBrbm93IHRoZSBvdXRjb21lIHZhcmlhYmxlLiAKClRoZSB3YXkgd2UgZG8gdGhpcyBpcyB0byB1c2UgZGF0YSB3aGVyZSB3ZSBoYXZlIGJvdGggdGhlIGZlYXR1cmVzICQoWF8xPXhfMSwgXGRvdHMgWF9wPXhfcCkkIGFuZCB0aGUgYWN0dWFsIG91dGNvbWUgJFkkIGRhdGEgdG8gX3RyYWluXyBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHRvIHByZWRpY3QgdGhlIG91dGNvbWUsIHdoaWNoIHdlIGNhbGwgJFxoYXR7WX0kLiAgCgpXaGVuIHdlIHNheSB0cmFpbiBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHdlIG1lYW4gdGhhdCB3ZSBlc3RpbWF0ZSBhIGZ1bmN0aW9uICRmJCB0aGF0IHVzZXMgdGhlIHByZWRpY3RvciB2YXJpYWJsZXMgJFgkIGFzIGlucHV0IG9yICRcaGF0e1l9ID0gZihYKSQuIAoKIyMgTUwgYXMgYW4gb3B0aW1pemF0aW9uIHByb2JsZW0KCklmIHdlIGFyZSBkb2luZyBhIGdvb2Qgam9iLCB0aGVuIG91ciBwcmVkaWN0ZWQgb3V0Y29tZSAkXGhhdHtZfSQgc2hvdWxkIGNsb3NlbHkgbWF0Y2ggb3VyIGFjdHVhbCBvdXRjb21lICRZJCB0aGF0IHdlIG9ic2VydmVkLiAKCkluIHRoaXMgd2F5LCB3ZSBjYW4gdGhpbmsgb2YgbWFjaGluZSBsZWFybmluZyAoTUwpIGFzIGFuIG9wdGltaXphdGlvbiBwcm9ibGVtIHRoYXQgdHJpZXMgdG8gbWluaW1pemUgdGhlIGRpc3RhbmNlIGJldHdlZW4gJFxoYXR7WX0gPSBmKFgpJCBhbmQgJFkkLiAKCiQkZChZIC0gZihYKSkkJApUaGUgY2hvaWNlIG9mIGRpc3RhbmNlIG1ldHJpYyAkZChcY2RvdCkkIGNhbiBiZSB0aGUgbWVhbiBvZiB0aGUgYWJzb2x1dGUgb3Igc3F1YXJlZCBkaWZmZXJlbmNlIG9yIHNvbWV0aGluZyBtb3JlIGNvbXBsaWNhdGVkLiAKCk11Y2ggb2YgdGhlIGZpZWxkcyBvZiBzdGF0aXN0aWNzIGFuZCBjb21wdXRlciBzY2llbmNlIGFyZSBmb2N1c2VkIG9uIGRlZmluaW5nICRmJCBhbmQgJGQkLgoKIyMgVGhlIHBhcnRzIG9mIGFuIE1MIHByb2JsZW0KClRvIHNldCB1cCBhIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBwcm9ibGVtLCB3ZSBuZWVkIGEgZmV3IGNvbXBvbmVudHMuClRvIHNvbHZlIGEgKHN0YW5kYXJkKSBtYWNoaW5lIGxlYXJuaW5nIHByb2JsZW0geW91IG5lZWQ6IAoKMS4gQSBkYXRhIHNldCB0byB0cmFpbiBmcm9tLiAKMi4gQW4gYWxnb3JpdGhtIG9yIHNldCBvZiBhbGdvcml0aG1zIHlvdSBjYW4gdXNlIHRvIHRyeSB2YWx1ZXMgb2YgJGYkCjMuIEEgZGlzdGFuY2UgbWV0cmljICRkJCBmb3IgbWVhc3VyaW5nIGhvdyBjbG9zZSAkWSQgaXMgdG8gJFxoYXR7WX0kCjQuIEEgZGVmaW5pdGlvbiBvZiB3aGF0IGEgImdvb2QiIGRpc3RhbmNlIGlzCgpXaGlsZSBlYWNoIG9mIHRoZXNlIGNvbXBvbmVudHMgaXMgYSBfdGVjaG5pY2FsXyBwcm9ibGVtLCB0aGVyZSBoYXMgYmVlbiBhIHRvbiBvZiB3b3JrIGFkZHJlc3NpbmcgdGhvc2UgdGVjaG5pY2FsIGRldGFpbHMuIFRoZSBtb3N0IHByZXNzaW5nIG9wZW4gaXNzdWUgaW4gbWFjaGluZSBsZWFybmluZyBpcyByZWFsaXppbmcgdGhhdCB0aG91Z2ggdGhlc2UgYXJlIF90ZWNobmljYWxfIHN0ZXBzIHRoZXkgYXJlIG5vdCBfb2JqZWN0aXZlXyBzdGVwcy4gSW4gb3RoZXIgd29yZHMsIGhvdyB5b3UgY2hvb3NlIHRoZSBkYXRhLCBhbGdvcml0aG0sIG1ldHJpYywgYW5kIGRlZmluaXRpb24gb2YgImdvb2QiIHNheXMgd2hhdCB5b3UgdmFsdWUgYW5kIGNhbiBkcmFtYXRpY2FsbHkgY2hhbmdlIHRoZSByZXN1bHRzLiBBIGNvdXBsZSBvZiBjYXNlcyB3aGVyZSB0aGlzIHdhcyBhIGJpZyBkZWFsIGFyZTogCgoxLiBbTWFjaGluZSBsZWFybmluZyBmb3IgcmVjaWRpdmlzbV0oaHR0cHM6Ly93d3cucHJvcHVibGljYS5vcmcvYXJ0aWNsZS9tYWNoaW5lLWJpYXMtcmlzay1hc3Nlc3NtZW50cy1pbi1jcmltaW5hbC1zZW50ZW5jaW5nKSAtIHBlb3BsZSBidWlsdCBNTCBtb2RlbHMgdG8gcHJlZGljdCB3aG8gd291bGQgcmUtY29tbWl0IGEgY3JpbWUuIEJ1dCB0aGVzZSBwcmVkaWN0aW9ucyB3ZXJlIGJhc2VkIG9uIGhpc3RvcmljYWxseSBiaWFzZWQgZGF0YSB3aGljaCBsZWQgdG8gYmlhc2VkIHByZWRpY3Rpb25zIGFib3V0IHdobyB3b3VsZCBjb21taXQgbmV3IGNyaW1lcy4gCjIuIFtEZWNpZGluZyBob3cgc2VsZiBkcml2aW5nIGNhcnMgc2hvdWxkIGFjdF0oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9hcnRpY2xlcy9kNDE1ODYtMDE4LTA3MTM1LTApIC0gc2VsZiBkcml2aW5nIGNhcnMgd2lsbCBoYXZlIHRvIG1ha2UgZGVjaXNpb25zIGFib3V0IGhvdyB0byBkcml2ZSwgd2hvIHRoZXkgbWlnaHQgaW5qdXJlLCBhbmQgaG93IHRvIGF2b2lkIGFjY2lkZW50cy4gRGVwZW5kaW5nIG9uIG91ciBjaG9pY2VzIGZvciAkZiQgYW5kICRkJCB0aGVzZSBtaWdodCBsZWFkIHRvIHdpbGRseSBkaWZmZXJlbnQga2luZHMgb2Ygc2VsZiBkcml2aW5nIGNhcnMuIFRyeSBvdXQgdGhlIFttb3JhbG1hY2hpbmVdKGh0dHA6Ly9tb3JhbG1hY2hpbmUubWl0LmVkdS8pIHRvIHNlZSBob3cgdGhpcyBsb29rcyBpbiBwcmFjdGljZS4gCgpOb3cgdGhhdCB3ZSBrbm93IGEgYml0IG1vcmUgYWJvdXQgbWFjaGluZSBsZWFybmluZywgbGV0J3MgYnVpbGQgYSBtb2RlbCB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIHVzaW5nIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrLiAKCiMgKipNYWNoaW5lIGxlYXJuaW5nIHdpdGggYHRpZHltb2RlbHNgKioKKioqClRoZSBnb2FsIGlzIHRvIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gdXNlcyB0aGUgZmVhdHVyZXMgYXMgaW5wdXQgYW5kIHByZWRpY3RzIGEgb3V0Y29tZSB2YXJpYWJsZSAob3IgYWlyIHBvbGx1dGlvbiBsZXZlbHMpIGluIHRoZSBzaXR1YXRpb24gd2hlcmUgd2UgZG8gbm90IGtub3cgdGhlIG91dGNvbWUgdmFyaWFibGUuIAoKVGhlIHdheSB3ZSBkbyB0aGlzIGlzIHRvIHVzZSBkYXRhIHdoZXJlIHdlIGhhdmUgYm90aCB0aGUgaW5wdXQgYW5kIG91dHB1dCBkYXRhIHRvIF90cmFpbl8gYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobS4gCgpUbyB0cmFpbiBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtLCB3ZSB3aWxsIHVzZSB0aGUgYHRpZHltb2RlbHNgIHBhY2thZ2UgZWNvc3lzdGVtLiAKCiMjIE92ZXJ2aWV3IAoKIyMjIFRoZSB0aWR5bW9kZWxzIGVjb3N5c3RlbQoKVG8gcGVyZm9ybSBvdXIgYW5hbHlzaXMgd2Ugd2lsbCBiZSB1c2luZyB0aGUgYHRpZHltb2RlbHNgIHN1aXRlIG9mIHBhY2thZ2VzLiAKWW91IG1heSBiZSBmYW1pbGlhciB3aXRoIHRoZSBvbGRlciBwYWNrYWdlcyBgY2FyZXRgIG9yIGBtbHJgIHdoaWNoIGFyZSBhbHNvIGZvciBtYWNoaW5lIGxlYXJuaW5nIGFuZCBtb2RlbGluZyBidXQgYXJlIG5vdCBhIHBhcnQgb2YgdGhlIGB0aWR5dmVyc2VgLiAKW01heCBLdWhuXShodHRwczovL3Jlc291cmNlcy5yc3R1ZGlvLmNvbS9hdXRob3JzL21heC1rdWhuKXt0YXJnZXQ9Il9ibGFuayJ9IGRlc2NyaWJlcyBgdGlkeW1vZGVsc2AgbGlrZSB0aGlzOgoKPiAiT3RoZXIgcGFja2FnZXMsIHN1Y2ggYXMgY2FyZXQgYW5kIG1sciwgaGVscCB0byBzb2x2ZSB0aGUgUiBtb2RlbCBBUEkgaXNzdWUuIFRoZXNlIHBhY2thZ2VzIGRvIGEgbG90IG9mIG90aGVyIHRoaW5ncyB0b286IHByZS1wcm9jZXNzaW5nLCBtb2RlbCB0dW5pbmcsIHJlc2FtcGxpbmcsIGZlYXR1cmUgc2VsZWN0aW9uLCBlbnNlbWJsaW5nLCBhbmQgc28gb24uIEluIHRoZSB0aWR5dmVyc2UsIHdlIHN0cml2ZSB0byBtYWtlIG91ciBwYWNrYWdlcyBtb2R1bGFyIGFuZCBwYXJzbmlwIGlzIGRlc2lnbmVkIG9ubHkgdG8gc29sdmUgdGhlIGludGVyZmFjZSBpc3N1ZS4gSXQgaXMgbm90IGRlc2lnbmVkIHRvIGJlIGEgZHJvcC1pbiByZXBsYWNlbWVudCBmb3IgY2FyZXQuClRoZSB0aWR5bW9kZWxzIHBhY2thZ2UgY29sbGVjdGlvbiwgd2hpY2ggaW5jbHVkZXMgcGFyc25pcCwgaGFzIG90aGVyIHBhY2thZ2VzIGZvciBtYW55IG9mIHRoZXNlIHRhc2tzLCBhbmQgdGhleSBhcmUgZGVzaWduZWQgdG8gd29yayB0b2dldGhlci4gV2UgYXJlIHdvcmtpbmcgdG93YXJkcyBoaWdoZXItbGV2ZWwgQVBJcyB0aGF0IGNhbiByZXBsaWNhdGUgYW5kIGV4dGVuZCB3aGF0IHRoZSBjdXJyZW50IG1vZGVsIHBhY2thZ2VzIGNhbiBkby4iCgpUaGVyZSBhcmUgbWFueSBSIHBhY2thZ2VzIGluIHRoZSBgdGlkeW1vZGVsc2AgZWNvc3lzdGVtLCB3aGljaCBhc3Npc3Qgd2l0aCB2YXJpb3VzIHN0ZXBzIGluIHRoZSBwcm9jZXNzIG9mIGJ1aWxkaW5nIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0uIFRoZXNlIGFyZSB0aGUgbWFpbiBwYWNrYWdlcywgYnV0IHRoZXJlIGFyZSBvdGhlcnMuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInNpbXBsZXRpZHltb2RlbHMucG5nIikpCmBgYAoKVGhpcyBpcyBhIHNjaGVtYXRpYyBvZiBob3cgdGhlc2UgcGFja2FnZXMgd29yayB0b2dldGhlciB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJNYWNoaW5lTGVhcm5pbmcucG5nIikpCmBgYAoKIyMjIEJlbmVmaXRzIG9mIHRpZHltb2RlbHMgIAoKVGhlIHR3byBtYWpvciBiZW5lZml0cyBvZiBgdGlkeW1vZGVsc2AgYXJlOiAKCjEuIFN0YW5kYXJkaXplZCB3b3JrZmxvdy9mb3JtYXQvbm90YXRpb24gYWNyb3NzIGRpZmZlcmVudCB0eXBlcyBvZiBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobXMgIAoKRGlmZmVyZW50IG5vdGF0aW9ucyBhcmUgcmVxdWlyZWQgZm9yIGRpZmZlcmVudCBhbGdvcml0aG1zIGFzIHRoZSBhbGdvcml0aG1zIGhhdmUgYmVlbiBkZXZlbG9wZWQgYnkgZGlmZmVyZW50IHBlb3BsZS4gVGhpcyB3b3VsZCByZXF1aXJlIHRoZSBwYWluc3Rha2luZyBwcm9jZXNzIG9mIHJlZm9ybWF0dGluZyB0aGUgZGF0YSB0byBiZSBjb21wYXRpYmxlIHdpdGggZWFjaCBhbGdvcml0aG0gaWYgbXVsdGlwbGUgYWxnb3JpdGhtcyB3ZXJlIHRlc3RlZC4KCjIuIENhbiBlYXNpbHkgbW9kaWZ5IHByZS1wcm9jZXNzaW5nLCBhbGdvcml0aG0gY2hvaWNlLCBhbmQgaHlwZXItcGFyYW1ldGVyIHR1bmluZyBtYWtpbmcgb3B0aW1pemF0aW9uIGVhc3kgIAoKTW9kaWZ5aW5nIGEgcGllY2Ugb2YgdGhlIG92ZXJhbGwgcHJvY2VzcyBpcyBub3cgZWFzaWVyIHRoYW4gYmVmb3JlIGJlY2F1c2UgbWFueSBvZiB0aGUgc3RlcHMgYXJlIHNwZWNpZmllZCB1c2luZyB0aGUgYHRpZHltb2RlbHNgIHBhY2thZ2VzIGluIGEgY29udmVuaWVudCBtYW5uZXIuIFRodXMgdGhlIGVudGlyZSBwcm9jZXNzIGNhbiBiZSByZXJ1biBhZnRlciBhIHNpbXBsZSBjaGFuZ2UgdG8gcHJlLXByb2Nlc3Npbmcgd2l0aG91dCBtdWNoIGRpZmZpY3VsdHkuCgoKCiMjIFNwbGl0dGluZyB0aGUgZGF0YQoKVGhlIGZpcnN0IHN0ZXAgYWZ0ZXIgZGF0YSBleHBsb3JhdGlvbiBpbiBtYWNoaW5lIGxlYXJuaW5nIGFuYWx5c2lzIGlzIHRvIFtzcGxpdCB0aGUgZGF0YV0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3RyYWluLXZhbGlkYXRpb24tYW5kLXRlc3Qtc2V0cy03MmNiNDBjYmE5ZTcpe3RhcmdldD0iX2JsYW5rIn0gaW50byAqKnRyYWluaW5nKiogYW5kICoqdGVzdGluZyoqIGRhdGEgc2V0cy4gCgpUaGUgdHJhaW5pbmcgZGF0YSBzZXQgd2lsbCBiZSB1c2VkIHRvIGJ1aWxkIGFuZCB0dW5lIG91ciBtb2RlbC4gClRoaXMgaXMgdGhlIGRhdGEgdGhhdCB0aGUgbW9kZWwgImxlYXJucyIgb24uIApUaGUgdGVzdGluZyBkYXRhIHNldCB3aWxsIGJlIHVzZWQgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciBtb2RlbCBpbiBhIG1vcmUgZ2VuZXJhbGl6YWJsZSB3YXkuIFdoYXQgZG8gd2UgbWVhbiBieSAiZ2VuZXJhbGl6YWJsZSI/CgpSZW1lbWJlciB0aGF0IG91ciBtYWluIGdvYWwgaXMgdG8gdXNlIG91ciBtb2RlbCB0byBiZSBhYmxlIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBsZXZlbHMgaW4gYXJlYXMgd2hlcmUgdGhlcmUgYXJlIG5vIGdyYXZpbWV0cmljIG1vbml0b3JzLiAKClRoZXJlZm9yZSwgaWYgb3VyIG1vZGVsIGlzIHJlYWxseSBnb29kIGF0IHByZWRpY3RpbmcgYWlyIHBvbGx1dGlvbiB3aXRoIHRoZSBkYXRhIHRoYXQgd2UgdXNlIHRvIGJ1aWxkIGl0LCBpdCBtaWdodCBub3QgZG8gdGhlIGJlc3Qgam9iIGZvciB0aGUgYXJlYXMgd2hlcmUgdGhlcmUgYXJlIGZldyB0byBubyBtb25pdG9ycy4gCgpUaGlzIHdvdWxkIGNhdXNlIHVzIHRvIGhhdmUgcmVhbGx5IGdvb2QgcHJlZGljdGlvbiBhY2N1cmFjeSBhbmQgd2UgbWlnaHQgYXNzdW1lIHRoYXQgd2Ugd2VyZSBnb2luZyB0byBkbyBhIGdvb2Qgam9iIGVzdGltYXRpbmcgYWlyIHBvbGx1dGlvbiBhbnkgdGltZSB3ZSB1c2Ugb3VyIG1vZGVsLCBidXQgaW4gZmFjdCB0aGlzIHdvdWxkIGxpa2VseSBub3QgYmUgdGhlIGNhc2UuIApUaGlzIHNpdHVhdGlvbiBpcyB3aGF0IHdlIGNhbGwgKipbb3ZlcmZpdHRpbmddKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS90cmFpbi10ZXN0LXNwbGl0LWFuZC1jcm9zcy12YWxpZGF0aW9uLWluLXB5dGhvbi04MGI2MWJlY2E0YjYpe3RhcmdldD0iX2JsYW5rIn0gKiouCgpPdmVyZml0dGluZyBoYXBwZW5zIHdoZW4gd2UgZW5kIHVwIG1vZGVsaW5nIG5vdCBvbmx5IHRoZSBtYWpvciByZWxhdGlvbnNoaXBzIGluIG91ciBkYXRhIGJ1dCBhbHNvIHRoZSBub2lzZSB3aXRoaW4gb3VyIGRhdGEuIAoKYGBge3IsIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTExMC8xKnRCRXJYWVZ2VHcyalNVWUs3dGhVMkEucG5nIikKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xMTEwLzEqdEJFclhZVnZUdzJqU1VZSzd0aFUyQS5wbmcpe3RhcmdldD0iX2JsYW5rIn0KCklmIHdlIGdldCBnb29kIHByZWRpY3Rpb24gd2l0aCBvdXIgdGVzdGluZyBzZXQsIHRoZW4gd2Uga25vdyB0aGF0IG91ciBtb2RlbCBjYW4gYmUgYXBwbGllZCB0byBvdGhlciBkYXRhIGFuZCB3aWxsIGxpa2VseSBwZXJmb3JtIHdlbGwuIFdlIHdpbGwgZGlzY3VzcyB0aGlzIG1vcmUgbGF0ZXIuCgpXZSB3aWxsIG5vdCB0b3VjaCB0aGUgdGVzdGluZyBzZXQgdW50aWwgd2UgaGF2ZSBjb21wbGV0ZWQgb3B0aW1pemluZyBvdXIgbW9kZWwgd2l0aCB0aGUgdHJhaW5pbmcgc2V0LiAKVGhpcyB3aWxsIGFsbG93IHVzIHRvIGhhdmUgYSBsZXNzIGJpYXNlZCBldmFsdWF0aW9uIG9mIGhvdyB3ZWxsIG91ciBtb2RlbCBjYW4gZG8gd2l0aCBvdGhlciBkYXRhIGJlc2lkZXMgdGhlIGRhdGEgdXNlZCBpbiB0aGUgdHJhaW5pbmcgc2V0IHRvIGJ1aWxkIHRoZSBtb2RlbC4gCklkZWFsbHksIHlvdSB3b3VsZCBhbHNvIHdhbnQgYSBjb21wbGV0ZWx5IGluZGVwZW5kZW50IGRhdGEgc2V0IHRvIGZ1cnRoZXIgdGVzdCB0aGUgcGVyZm9ybWFuY2Ugb2YgeW91ciBtb2RlbC4KClRvIHNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3RpbmcsIHdlIHdpbGwgdXNlIHRoZSBgaW5pdGlhbF9zcGxpdCgpYCBmdW5jdGlvbiBpbiB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgdG8gc3BlY2lmeSBob3cgd2Ugd2FudCB0byBzcGxpdCBvdXIgZGF0YS4KCgpgYGB7ciwgZWNobz1GQUxTRX0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInNwbGl0LnBuZyIpKQpgYGAKCmBgYHtyfQpzZXQuc2VlZCgxMjM0KQpwbV9zcGxpdCA8LSByc2FtcGxlOjppbml0aWFsX3NwbGl0KGRhdGEgPSBwbSwgcHJvcCA9IDIvMykKcG1fc3BsaXQKYGBgCgpBIGNvdXBsZSBvZiBub3RlcyBmcm9tIHRoZSBjb2RlIGFib3ZlOiAKCi0gVHlwaWNhbGx5LCBkYXRhIGFyZSBzcGxpdCBpbnRvIDMvNCBvZiB0aGUgb2JzZXJ2YXRpb25zIGZvciB0cmFpbmluZyBhbmQgMS80IGZvciB0ZXN0aW5nLiBUaGlzIGlzIHRoZSBkZWZhdWx0IHByb3BvcnRpb24gYW5kIGRvZXMgbm90IG5lZWQgdG8gYmUgc3BlY2lmaWVkLiBIb3dldmVyLCB5b3UgY2FuIGNoYW5nZSB0aGUgcHJvcG9ydGlvbiB1c2luZyB0aGUgYHByb3BgIGFyZ3VtZW50LCB3aGljaCB3ZSB3aWxsIGRvIHRoYXQgaGVyZSBmb3IgaWxsdXN0cmF0aXZlIHB1cnBvc2VzLgotIFNpbmNlIHRoZSBzcGxpdCBpcyBwZXJmb3JtZWQgcmFuZG9tbHksIGl0IGlzIGEgZ29vZCBpZGVhIHRvIHVzZSB0aGUgYHNldC5zZWVkKClgIGZ1bmN0aW9uIGluIGJhc2UgUiB0byBlbnN1cmUgdGhhdCBpZiB5b3VyIHJlcnVuIHlvdXIgY29kZSB0aGF0IHlvdXIgc3BsaXQgd2lsbCBiZSB0aGUgc2FtZSBuZXh0IHRpbWUuCi0gV2UgY2FuIHNlZSB0aGUgbnVtYmVyIG9mIG1vbml0b3JzIGluIG91ciB0cmFpbmluZywgdGVzdGluZywgYW5kIG9yaWdpbmFsIGRhdGEgYnkgdHlwaW5nIGluIHRoZSBuYW1lIG9mIG91ciBzcGxpdCBvYmplY3QuIFRoZSByZXN1bHQgd2lsbCBsb29rIGxpa2UgdGhpczoKPHRyYWluaW5nIGRhdGEgc2FtcGxlIG51bWJlciwgdGVzdGluZyBkYXRhIHNhbXBsZSBudW1iZXIsIG9yaWdpbmFsIHNhbXBsZSBudW1iZXI+IAoKTm93LCB5b3UgY2FuIGFsc28gc3BlY2lmeSBhIHZhcmlhYmxlIHRvIHN0cmF0aWZ5IGJ5IHdpdGggdGhlIGBzdHJhdGFgIGFyZ3VtZW50LiAKVGhpcyBpcyB1c2VmdWwgaWYgeW91IGhhdmUgaW1iYWxhbmNlZCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYW5kIHlvdSB3b3VsZCBsaWtlIHRvIGludGVudGlvbmFsbHkgbWFrZSBzdXJlIHRoYXQgdGhlcmUgYXJlIHNpbWlsYXIgbnVtYmVyIG9mIHNhbXBsZXMgb2YgdGhlIHJhcmVyIGNhdGVnb3JpZXMgaW4gYm90aCB0aGUgdGVzdGluZyBhbmQgdHJhaW5pbmcgc2V0cy4gCk90aGVyd2lzZSB0aGUgc3BsaXQgaXMgcGVyZm9ybWVkIHJhbmRvbWx5LiAKCkFjY29yZGluZyB0byB0aGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9yc2FtcGxlL3ZlcnNpb25zLzAuMC41L3RvcGljcy9pbml0aWFsX3NwbGl0KSBmb3IgdGhlIGByc2FtcGxlYCBwYWNrYWdlOgoKPiBUaGUgc3RyYXRhIGFyZ3VtZW50IGNhdXNlcyB0aGUgcmFuZG9tIHNhbXBsaW5nIHRvIGJlIGNvbmR1Y3RlZCB3aXRoaW4gdGhlIHN0cmF0aWZpY2F0aW9uIHZhcmlhYmxlLiBUaGlzIGNhbiBoZWxwIGVuc3VyZSB0aGF0IHRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgaW4gdGhlIHRyYWluaW5nIGRhdGEgaXMgZXF1aXZhbGVudCB0byB0aGUgcHJvcG9ydGlvbnMgaW4gdGhlIG9yaWdpbmFsIGRhdGEgc2V0LgoKSW4gdGhlIGNhc2Ugd2l0aCBvdXIgZGF0YSBzZXQsIHBlcmhhcHMgd2Ugd291bGQgbGlrZSBvdXIgdHJhaW5pbmcgc2V0IHRvIGhhdmUgc2ltaWxhciBwcm9wb3J0aW9ucyBvZiBtb25pdG9ycyBmcm9tIGVhY2ggb2YgdGhlIHN0YXRlcyBhcyBpbiB0aGUgaW5pdGlhbCBkYXRhLiAKVGhpcyBtaWdodCBiZSB1c2VmdWwgaWYgd2Ugd2FudCBvdXIgbW9kZWwgdG8gYmUgZ2VuZXJhbGl6YWJsZSBhY3Jvc3MgYWxsIG9mIHRoZSBzdGF0ZXMuCgpXZSBjYW4gc2VlIHRoYXQgaW5kZWVkIHRoZXJlIGFyZSBkaWZmZXJlbnQgcHJvcG9ydGlvbnMgb2YgbW9uaXRvcnMgaW4gZWFjaCBzdGF0ZSBieSB1c2luZyB0aGUgYGNvdW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIAoKYGBge3IsIGV2YWwgPSBGQUxTRX0KY291bnQocG0sIHN0YXRlKQpgYGAKClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6CgojIyMjIHsuc2Nyb2xsYWJsZSB9CgpgYGB7ciwgZWNobz1GQUxTRX0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpjb3VudChwbSwgc3RhdGUpICU+JQogIHByaW50KG4gPSAxZTMpCmBgYAojIyMjCgpJZiBvdXIgZGF0YSBzZXQgd2VyZSBsYXJnZSBlbm91Z2ggaXQgbWlnaHQgYmUgbmljZSB0aGVuIHRvIHN0cmF0aWZ5IGJ5IHN0YXRlIHVzaW5nIHRoZSBgc3RyYXRhID0gInN0YXRlImAgYXJndW1lbnQgaW4gYGluaXRpYWxfc3BsaXQoKWAsIGJ1dCBvdXIgZGF0YSBpcyB1bmZvcnR1bmF0ZWx5IG5vdCBsYXJnZSBlbm91Z2guIAoKSW1wb3J0YW50bHkgdGhlIGBpbml0aWFsX3NwbGl0KClgIGZ1bmN0aW9uIG9ubHkgZGV0ZXJtaW5lcyB3aGF0IHJvd3Mgb2Ygb3VyIGBwbWAgZGF0YSBmcmFtZSBzaG91bGQgYmUgYXNzaWduZWQgZm9yIHRyYWluaW5nIG9yIHRlc3RpbmcsIGl0IGRvZXMgbm90IGFjdHVhbGx5IHNwbGl0IHRoZSBkYXRhLiAKClRvIGV4dHJhY3QgdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIGRhdGEgd2UgY2FuIHVzZSB0aGUgYHRyYWluaW5nKClgIGFuZCBgdGVzdGluZygpYCBmdW5jdGlvbnMgYWxzbyBvZiB0aGUgYHJzYW1wbGVgIHBhY2thZ2UuCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyfQp0cmFpbl9wbSA8LXJzYW1wbGU6OnRyYWluaW5nKHBtX3NwbGl0KQp0ZXN0X3BtIDwtcnNhbXBsZTo6dGVzdGluZyhwbV9zcGxpdCkKIAojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCmNvdW50KHRyYWluX3BtLCBzdGF0ZSkKY291bnQodGVzdF9wbSwgc3RhdGUpCmBgYAojIyMjCgoKCiMjIFByZXBhcmluZyBmb3IgcHJlLXByb2Nlc3NpbmcgdGhlIGRhdGEKCkFmdGVyIHNwbGl0dGluZyB0aGUgZGF0YSwgdGhlIG5leHQgc3RlcCBpcyB0byBwcm9jZXNzIHRoZSB0cmFpbmluZyBhbmQgdGVzdGluZyBkYXRhIHNvIHRoYXQgdGhlIGRhdGEgYXJlIGFyZSBjb21wYXRpYmxlIGFuZCBvcHRpbWl6ZWQgdG8gYmUgdXNlZCB3aXRoIHRoZSBtb2RlbC4gClRoaXMgaW52b2x2ZXMgYXNzaWduaW5nIHZhcmlhYmxlcyB0byBzcGVjaWZpYyByb2xlcyB3aXRoaW4gdGhlIG1vZGVsIGFuZCBwcmUtcHJvY2Vzc2luZyBsaWtlIHNjYWxpbmcgdmFyaWFibGVzIGFuZCByZW1vdmluZyByZWR1bmRhbnQgdmFyaWFibGVzLiAKVGhpcyBwcm9jZXNzIGlzIGFsc28gY2FsbGVkIGZlYXR1cmUgZW5naW5lZXJpbmcuCgpUbyBkbyB0aGlzIGluIGB0aWR5bW9kZWxzYCwgd2Ugd2lsbCBjcmVhdGUgd2hhdCdzIGNhbGxlZCBhICJyZWNpcGUiIHVzaW5nIHRoZSBgcmVjaXBlc2AgcGFja2FnZSwgd2hpY2ggaXMgYSBzdGFuZGFyZGl6ZWQgZm9ybWF0IGZvciBhIHNlcXVlbmNlIG9mIHN0ZXBzIGZvciBwcmUtcHJvY2Vzc2luZyB0aGUgZGF0YS4KVGhpcyBjYW4gYmUgdmVyeSB1c2VmdWwgYmVjYXVzZSBpdCBtYWtlcyB0ZXN0aW5nIG91dCBkaWZmZXJlbnQgcHJlLXByb2Nlc3Npbmcgc3RlcHMgb3IgZGlmZmVyZW50IGFsZ29yaXRobXMgd2l0aCB0aGUgc2FtZSBwcmUtcHJvY2Vzc2luZyB2ZXJ5IGVhc3kgYW5kIHJlcHJvZHVjaWJsZS4KQ3JlYXRpbmcgYSByZWNpcGUgc3BlY2lmaWVzICoqaG93IGEgZGF0YSBmcmFtZSBvZiBwcmVkaWN0b3JzIHNob3VsZCBiZSBjcmVhdGVkKiogLSBpdCBzcGVjaWZpZXMgd2hhdCB2YXJpYWJsZXMgdG8gYmUgdXNlZCBhbmQgdGhlIHByZS1wcm9jZXNzaW5nIHN0ZXBzLCBidXQgaXQgKipkb2VzIG5vdCBleGVjdXRlIHRoZXNlIHN0ZXBzKiogb3IgY3JlYXRlIHRoZSBkYXRhIGZyYW1lIG9mIHByZWRpY3RvcnMuCgojIyMgU3RlcCAxOiBTcGVjaWZ5IHZhcmlhYmxlcyByb2xlcyB3aXRoIGByZWNpcGUoKWAgZnVuY3Rpb24KClRoZSBmaXJzdCB0aGluZyB0byBkbyB0byBjcmVhdGUgYSByZWNpcGUgaXMgdG8gc3BlY2lmeSB3aGljaCB2YXJpYWJsZXMgd2Ugd2lsbCBiZSB1c2luZyBhcyBvdXIgb3V0Y29tZSBhbmQgcHJlZGljdG9ycyB1c2luZyB0aGUgYHJlY2lwZSgpYCBmdW5jdGlvbi4gCkluIHRlcm1zIG9mIHRoZSBtZXRhcGhvciBvZiBiYWtpbmcsIHdlIGNhbiB0aGluayBvZiB0aGlzIGFzIGxpc3Rpbmcgb3VyIGluZ3JlZGllbnRzLiAKVHJhbnNsYXRpbmcgdGhpcyB0byB0aGUgYHJlY2lwZXNgIHBhY2thZ2UsIHdlIHVzZSB0aGUgYHJlY2lwZSgpYCBmdW5jdGlvbiB0byBhc3NpZ24gcm9sZXMgdG8gYWxsIHRoZSB2YXJpYWJsZXMuIAoKTGV0J3MgdHJ5IHRoZSBzaW1wbGVzdCByZWNpcGUgd2l0aCBubyBwcmUtcHJvY2Vzc2luZyBzdGVwczogc2ltcGx5IGxpc3QgdGhlIG91dGNvbWUgYW5kIHByZWRpY3RvciB2YXJpYWJsZXMuCgpXZSBjYW4gZG8gc28gaW4gdHdvIHdheXM6ICAKCjEpIFVzaW5nIGZvcm11bGEgbm90YXRpb24gIAoyKSBBc3NpZ25pbmcgcm9sZXMgdG8gZWFjaCB2YXJpYWJsZSAgCgpMZXQncyBsb29rIGF0IHRoZSBmaXJzdCB3YXkgdXNpbmcgZm9ybXVsYSBub3RhdGlvbiwgd2hpY2ggbG9va3MgbGlrZSB0aGlzOiAgCgpvdXRjb21lKHMpIH4gcHJlZGljdG9yKHMpICAKCklmIGluIHRoZSBjYXNlIG9mIG11bHRpcGxlIHByZWRpY3RvcnMgb3IgYSBtdWx0aXZhcmlhdGUgc2l0dWF0aW9uIHdpdGggdHdvIG91dGNvbWVzLCB1c2UgYSBwbHVzIHNpZ246ICAKCm91dGNvbWUxICsgb3V0Y29tZTIgfiBwcmVkaWN0b3IxICsgcHJlZGljdG9yMiAgCgpJZiB3ZSB3YW50IHRvIGluY2x1ZGUgYWxsIHByZWRpY3RvcnMgd2UgY2FuIHVzZSBhIHBlcmlvZCBsaWtlIHNvOiAgCgpvdXRjb21lX3ZhcmlhYmxlX25hbWUgfiAuICAKCk5vdyB3aXRoIG91ciBkYXRhLCB3ZSB3aWxsIHN0YXJ0IGJ5IG1ha2luZyBhIHJlY2lwZSBmb3Igb3VyIHRyYWluaW5nIGRhdGEuCklmIHlvdSByZWNhbGwsIHRoZSBjb250aW51b3VzIG91dGNvbWUgdmFyaWFibGUgaXMgYHZhbHVlYCAodGhlIGF2ZXJhZ2UgYW5udWFsIGdyYXZpbWV0cmljIG1vbml0b3IgUE1+Mi41fiBjb25jZW50cmF0aW9uIGluIHVnL21eM14pLiAKT3VyIGZlYXR1cmVzIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSBhcmUgYWxsIHRoZSBvdGhlciB2YXJpYWJsZXMgZXhjZXB0IHRoZSBtb25pdG9yIElELCB3aGljaCBpcyBhbiBgaWRgIHZhcmlhYmxlLgoKVGhlIHJlYXNvbiBub3QgdG8gaW5jbHVkZSB0aGUgYGlkYCB2YXJpYWJsZSBpcyBiZWNhdXNlIHRoaXMgdmFyaWFibGUgaW5jbHVkZXMgdGhlIGNvdW50eSBudW1iZXIgYW5kIGEgbnVtYmVyIGRlc2lnbmF0aW5nIHdoaWNoIHBhcnRpY3VsYXIgbW9uaXRvciB0aGUgdmFsdWVzIGNhbWUgZnJvbSAob2YgdGhlIG1vbml0b3JzIHRoZXJlIGFyZSBpbiB0aGF0IGNvdW50eSkuIApTaW5jZSB0aGlzIG51bWJlciBpcyBhcmJpdHJhcnkgYW5kIHRoZSBjb3VudHkgaW5mb3JtYXRpb24gaXMgYWxzbyBnaXZlbiBpbiB0aGUgZGF0YSwgYW5kIHRoZSBmYWN0IHRoYXQgZWFjaCBtb25pdG9yIG9ubHkgaGFzIG9uZSB2YWx1ZSBpbiB0aGUgYHZhbHVlYCB2YXJpYWJsZSwgbm90aGluZyBpcyBnYWluZWQgYnkgaW5jbHVkaW5nIHRoaXMgdmFyaWFibGUgYW5kIGl0IG1heSBpbnN0ZWFkIGludHJvZHVjZSBub2lzZS4gCkhvd2V2ZXIsIGl0IGlzIHVzZWZ1bCB0byBrZWVwIHRoaXMgZGF0YSB0byB0YWtlIGEgbG9vayBhdCB3aGF0IGlzIGhhcHBlbmluZyBsYXRlci4gCldlIHdpbGwgc2hvdyB5b3Ugd2hhdCB0byBkbyBpbiB0aGlzIGNhc2UgaW4ganVzdCBhIGJpdC4KCkluIHRoZSBzaW1wbGVzdCBjYXNlLCB3ZSBtaWdodCB1c2UgYWxsIHByZWRpY3RvcnMgbGlrZSB0aGlzOgoKYGBge3J9CnNpbXBsZV9yZWMgPC0gdHJhaW5fcG0gJT4lCiAgcmVjaXBlczo6cmVjaXBlKHZhbHVlIH4gLikKCnNpbXBsZV9yZWMKYGBgCgpXZSBzZWUgYSByZWNpcGUgaGFzIGJlZW4gY3JlYXRlZCB3aXRoIDEgb3V0Y29tZSB2YXJpYWJsZSBhbmQgNDkgcHJlZGljdG9yIHZhcmlhYmxlcyAob3IgZmVhdHVyZXMpLiAKQWxzbywgbm90aWNlIGhvdyB3ZSBuYW1lZCB0aGUgb3V0cHV0IG9mIGByZWNpcGUoKWAuIApUaGUgbmFtaW5nIGNvbnZlbnRpb24gZm9yIHJlY2lwZSBvYmplY3RzIGlzIGAqX3JlY2Agb3IgYHJlY2AuIAoKTm93LCBsZXQncyBnZXQgYmFjayB0byB0aGUgYGlkYCB2YXJpYWJsZS4gCkluc3RlYWQgb2YgaW5jbHVkaW5nIGl0IGFzIGEgcHJlZGljdG9yIHZhcmlhYmxlLCB3ZSBjb3VsZCBhbHNvIHVzZSB0aGUgYHVwZGF0ZV9yb2xlKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZS4KCmBgYHtyfQpzaW1wbGVfcmVjIDwtIHRyYWluX3BtICU+JQogIHJlY2lwZXM6OnJlY2lwZSh2YWx1ZSB+IC4pICU+JQogIHJlY2lwZXM6OnVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpCgpzaW1wbGVfcmVjCmBgYAoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIGhlcmUgbGVhcm4gbW9yZSBhYm91dCB0aGUgd29ya2luZyB3aXRoIGBpZGAgdmFyaWFibGVzIDwvc3VtbWFyeT4KClRoaXMgb3B0aW9uIHdvcmtzIHdlbGwgd2l0aCB0aGUgbmV3ZXIgYHdvcmtmbG93c2AgcGFja2FnZSwgaG93ZXZlciBgaWRgIHZhcmlhYmxlcyBhcmUgb2Z0ZW4gZHJvcHBlZCBmcm9tIGFuYWx5c2VzIHRoYXQgZG8gbm90IHVzZSB0aGlzIG5ld2VyIHBhY2thZ2UgYXMgdGhleSBjYW4gbWFrZSB0aGUgcHJvY2VzcyBkaWZmaWN1bHQgd2l0aCB1c2luZyB0aGUgYHBhcnNuaXBgIHBhY2thZ2UgYWxvbmUgZHVlIHRvIHRoZSBmYWN0IHRoYXQgbmV3IGxldmVscyAob3IgcG9zc2libGUgdmFsdWVzKSBtYXkgYmUgaW50cm9kdWNlZCB3aXRoIHRoZSB0ZXN0aW5nIGRhdGEuCgo8L2RldGFpbHM+CgpXZSBjb3VsZCBhbHNvIHNwZWNpZnkgdGhlIG91dGNvbWUgYW5kIHByZWRpY3RvcnMgaW4gdGhlIHNhbWUgd2F5IGFzIHdlIGp1c3Qgc3BlY2lmaWVkIHRoZSBpZCB2YXJpYWJsZS4gClBsZWFzZSBzZWUgW2hlcmVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvcmVjaXBlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIGV4YW1wbGVzIG9mIG90aGVyIHJvbGVzIGZvciB2YXJpYWJsZXMuIApUaGUgcm9sZSBjYW4gYmUgYWN0dWFsbHkgYmUgYW55IHZhbHVlLiAKClRoZSBvcmRlciBpcyBpbXBvcnRhbnQgaGVyZSwgYXMgd2UgZmlyc3QgbWFrZSBhbGwgdmFyaWFibGVzIHByZWRpY3RvcnMgYW5kIHRoZW4gb3ZlcnJpZGUgdGhpcyByb2xlIGZvciB0aGUgb3V0Y29tZSBhbmQgYGlkYCB2YXJpYWJsZS4gCldlIHdpbGwgdXNlIHRoZSBgZXZlcnl0aGluZygpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIHRvIHN0YXJ0IHdpdGggYWxsIG9mIHRoZSB2YXJpYWJsZXMgaW4gYHRyYWluX3BtYC4KCmBgYHtyfQpzaW1wbGVfcmVjIDwtcmVjaXBlKHRyYWluX3BtKSAlPiUKICAgIHVwZGF0ZV9yb2xlKGV2ZXJ5dGhpbmcoKSwgbmV3X3JvbGUgPSAicHJlZGljdG9yIiklPiUKICAgIHVwZGF0ZV9yb2xlKHZhbHVlLCBuZXdfcm9sZSA9ICJvdXRjb21lIiklPiUKICAgIHVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpCgpzaW1wbGVfcmVjCmBgYAoKSWYgd2Ugd2FudCB0byB0YWtlIGEgbG9vayBhdCBvdXIgZm9ybXVsYSBmcm9tIG91ciByZWNpcGUsIHdlIGNhbiBkbyB1c2UgdGhlIGBmb3JtdWxhKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RhdHNgIHBhY2thZ2UuCgpgYGB7cn0KZm9ybXVsYShzaW1wbGVfcmVjKQpgYGAKCldlIGNhbiBhbHNvIHZpZXcgb3VyIHJlY2lwZSBpbiBtb3JlIGRldGFpbCB1c2luZyB0aGUgYmFzZSBgc3VtbWFyeSgpYCBmdW5jdGlvbi4KCmBgYHtyfQpzdW1tYXJ5KHNpbXBsZV9yZWMpCmBgYAoKVG8gc3VtbWFyaXplIHRoaXMgc3RlcCwgd2UgdXNlIHRoZSBgcmVjaXBlKClgIGZ1bmN0aW9uIHRvIGFzc2lnbiByb2xlcyB0byBhbGwgdGhlIHZhcmlhYmxlczogCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIlN0YXJ0aW5nX2FfcmVjaXBlX3JlY2lwZXMxLnBuZyIpKQpgYGAKCgojIyMgU3RlcCAyOiBTcGVjaWZ5IHRoZSBwcmUtcHJvY2Vzc2luZyBzdGVwcyB3aXRoIGBzdGVwKigpYCBmdW5jdGlvbnMKCk5leHQsIHdlIHVzZSB0aGUgYHN0ZXAqKClgIGZ1bmN0aW9ucyBmcm9tIHRoZSBgcmVjaXBlYCBwYWNrYWdlIHRvIHNwZWNpZnkgcHJlLXByb2Nlc3Npbmcgc3RlcHMuIAoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJNYWtpbmdfYV9yZWNpcGVfcmVjaXBlczIucG5nIikpCmBgYAoKKipUaGlzIFtsaW5rXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvcmVmZXJlbmNlL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gYW5kIHRoaXMgW2xpbmtdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZWNpcGVzL3JlY2lwZXMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHNob3cgdGhlIG1hbnkgb3B0aW9ucyBmb3IgcmVjaXBlIHN0ZXAgZnVuY3Rpb25zLioqCgo8dT5UaGVyZSBhcmUgc3RlcCBmdW5jdGlvbnMgZm9yIGEgdmFyaWV0eSBvZiBwdXJwb3Nlczo8L3U+CgoxLiBbKipJbXB1dGF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ltcHV0YXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGZpbGxpbmcgaW4gbWlzc2luZyB2YWx1ZXMgYmFzZWQgb24gdGhlIGV4aXN0aW5nIGRhdGEgCjIuIFsqKlRyYW5zZm9ybWF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RhdGFfdHJhbnNmb3JtYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGNoYW5naW5nIGFsbCB2YWx1ZXMgb2YgYSB2YXJpYWJsZSBpbiB0aGUgc2FtZSB3YXksIHR5cGljYWxseSB0byBtYWtlIGl0IG1vcmUgbm9ybWFsIG9yIGVhc2llciB0byBpbnRlcnByZXQKMy4gWyoqRGlzY3JldGl6YXRpb24qKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGlzY3JldGl6YXRpb25fb2ZfY29udGludW91c19mZWF0dXJlcyl7dGFyZ2V0PSJfYmxhbmsifSAtLSBjb252ZXJ0aW5nIGNvbnRpbnVvdXMgdmFsdWVzIGludG8gZGlzY3JldGUgb3Igbm9taW5hbCB2YWx1ZXMgLSBiaW5uaW5nIGZvciBleGFtcGxlIHRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIHBvc3NpYmxlIGxldmVscyAoSG93ZXZlciB0aGlzIGlzIGdlbmVyYWxseSBub3QgYWR2aXNhYmxlISkKNC4gWyoqRW5jb2RpbmcgLyBDcmVhdGluZyBEdW1teSBWYXJpYWJsZXMqKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRHVtbXlfdmFyaWFibGVfKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGNyZWF0aW5nIGEgbnVtZXJpYyBjb2RlIGZvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKKFsqKk1vcmUgb24gRHVtbXkgVmFyaWFibGVzIGFuZCBvbmUgaG90IGVuY29kaW5nKipdKGh0dHBzOi8vbWVkaXVtLmNvbS9wL2I1ODQwYmUzYzQxYS9yZXNwb25zZXMvc2hvdyl7dGFyZ2V0PSJfYmxhbmsifSkKNS4gWyoqRGF0YSB0eXBlIGNvbnZlcnNpb25zKipdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9oYWJsYXIvdmlnbmV0dGVzL2NvbnZlcnQuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgLS0gd2hpY2ggbWVhbnMgY2hhbmdpbmcgZnJvbSBpbnRlZ2VyIHRvIGZhY3RvciBvciBudW1lcmljIHRvIGRhdGUgZXRjLgo2LiBbKipJbnRlcmFjdGlvbioqXShodHRwczovL3N0YXRpc3RpY3NieWppbS5jb20vcmVncmVzc2lvbi9pbnRlcmFjdGlvbi1lZmZlY3RzLyl7dGFyZ2V0PSJfYmxhbmsifSAgdGVybSBhZGRpdGlvbiB0byB0aGUgbW9kZWwgLS0gd2hpY2ggbWVhbnMgdGhhdCB3ZSB3b3VsZCBiZSBtb2RlbGluZyBmb3IgcHJlZGljdG9ycyB0aGF0IHdvdWxkIGluZmx1ZW5jZSB0aGUgY2FwYWNpdHkgb2YgZWFjaCBvdGhlciB0byBwcmVkaWN0IHRoZSBvdXRjb21lCjcuIFsqKk5vcm1hbGl6YXRpb24qKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTm9ybWFsaXphdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gLS0gY2VudGVyaW5nIGFuZCBzY2FsaW5nIHRoZSBkYXRhIHRvIGEgc2ltaWxhciByYW5nZSBvZiB2YWx1ZXMKOC4gWyoqRGltZW5zaW9uYWxpdHkgUmVkdWN0aW9uLyBTaWduYWwgRXh0cmFjdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaW1lbnNpb25hbGl0eV9yZWR1Y3Rpb24pe3RhcmdldD0iX2JsYW5rIn0gLS0gcmVkdWNpbmcgdGhlIHNwYWNlIG9mIGZlYXR1cmVzIG9yIHByZWRpY3RvcnMgdG8gYSBzbWFsbGVyIHNldCBvZiB2YXJpYWJsZXMgdGhhdCBjYXB0dXJlIHRoZSB2YXJpYXRpb24gb3Igc2lnbmFsIGluIHRoZSBvcmlnaW5hbCB2YXJpYWJsZXMgKGV4LiBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzIGFuZCBJbmRlcGVuZGVudCBDb21wb25lbnQgQW5hbHlzaXMpCjkuICoqRmlsdGVyaW5nKiogLS0gZmlsdGVyaW5nIG9wdGlvbnMgZm9yIHJlbW92aW5nIHZhcmlhYmxlcyAoZXguIHJlbW92ZSB2YXJpYWJsZXMgdGhhdCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgdG8gb3RoZXJzIG9yIHJlbW92ZSB2YXJpYWJsZXMgd2l0aCB2ZXJ5IGxpdHRsZSB2YXJpYW5jZSBhbmQgdGhlcmVmb3JlIGxpa2VseSBsaXR0bGUgcHJlZGljdGl2ZSBjYXBhY2l0eSkKMTAuIFsqKlJvdyBvcGVyYXRpb25zKipdKGh0dHBzOi8vdGFydGFydXMub3JnL2dhcmV0aC9tYXRocy9MaW5lYXJfQWxnZWJyYS9yb3dfb3BlcmF0aW9ucy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gLS0gcGVyZm9ybWluZyBmdW5jdGlvbnMgb24gdGhlIHZhbHVlcyB3aXRoaW4gdGhlIHJvd3MgIChleC4gcmVhcnJhbmdpbmcsIGZpbHRlcmluZywgaW1wdXRpbmcpCjExLiAqKkNoZWNraW5nIGZ1bmN0aW9ucyoqIC0tIFNhbml0eSBjaGVja3MgdG8gbG9vayBmb3IgbWlzc2luZyB2YWx1ZXMsIHRvIGxvb2sgYXQgdGhlIHZhcmlhYmxlIGNsYXNzZXMgZXRjLgoKQWxsIG9mIHRoZSBzdGVwIGZ1bmN0aW9ucyBsb29rIGxpa2UgYHN0ZXBfKigpYCB3aXRoIHRoZSBgKmAgcmVwbGFjZWQgd2l0aCBhIG5hbWUsIGV4Y2VwdCBmb3IgdGhlIGNoZWNrIGZ1bmN0aW9ucyB3aGljaCBsb29rIGxpa2UgYGNoZWNrXyooKWAuCgpUaGVyZSBhcmUgc2V2ZXJhbCB3YXlzIHRvIHNlbGVjdCB3aGF0IHZhcmlhYmxlcyB0byBhcHBseSBzdGVwcyB0bzogIAoKMS4gVXNpbmcgYHRpZHlzZWxlY3RgIG1ldGhvZHM6IGBjb250YWlucygpYCwgYG1hdGNoZXMoKWAsIGBzdGFydHNfd2l0aCgpYCwgYGVuZHNfd2l0aCgpYCwgYGV2ZXJ5dGhpbmcoKWAsIGBudW1fcmFuZ2UoKWAgIAoyLiBVc2luZyB0aGUgdHlwZTogYGFsbF9ub21pbmFsKClgLCBgYWxsX251bWVyaWMoKWAgLCBgaGFzX3R5cGUoKWAgCjMuIFVzaW5nIHRoZSByb2xlOiBgYWxsX3ByZWRpY3RvcnMoKWAsIGBhbGxfb3V0Y29tZXMoKWAsIGBoYXNfcm9sZSgpYAo0LiBVc2luZyB0aGUgbmFtZSAtIHVzZSB0aGUgYWN0dWFsIG5hbWUgb2YgdGhlIHZhcmlhYmxlL3ZhcmlhYmxlcyBvZiBpbnRlcmVzdCAgCgpMZXQncyB0cnkgYWRkaW5nIHNvbWUgc3RlcHMgdG8gb3VyIHJlY2lwZS4KCgpXZSBtaWdodCB3YW50IHRvIHBvdGVudGlhbGx5IFtvbmUgaG90IGVuY29kZV0oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS93aHktb25lLWhvdC1lbmNvZGUtZGF0YS1pbi1tYWNoaW5lLWxlYXJuaW5nLyl7dGFyZ2V0PSJfYmxhbmsifSBzb21lIG9mIG91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgc28gdGhhdCB0aGV5IGNhbiBiZSB1c2VkIHdpdGggY2VydGFpbiBhbGdvcml0aG1zLiAKCldlIGNhbiBkbyB0aGlzIHdpdGggdGhlIGBzdGVwX2R1bW15KClgIGZ1bmN0aW9uIGFuZCB0aGUgYG9uZV9ob3QgPSBUUlVFYCBhcmd1bWVudC4gCk9uZSBob3QgZW5jb2RpbmcgbWVhbnMgdGhhdCB3ZSBkbyBub3Qgc2ltcGx5IGVuY29kZSBvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzIG51bWVyaWNhbGx5LCBhcyBvdXIgbnVtZXJpYyBhc3NpZ25tZW50cyBjYW4gYmUgaW50ZXJwcmV0ZWQgYnkgYWxnb3JpdGhtcyBhcyBoYXZpbmcgYSBwYXJ0aWN1bGFyIHJhbmsgb3Igb3JkZXIuIApJbnN0ZWFkLCBiaW5hcnkgdmFyaWFibGVzIG1hZGUgb2YgMXMgYW5kIDBzIGFyZSB1c2VkIHRvIGFyYml0cmFyaWx5IGFzc2lnbiBhIG51bWVyaWMgdmFsdWUgdGhhdCBoYXMgbm8gYXBwYXJlbnQgb3JkZXIuCgpgYGB7cn0Kc2ltcGxlX3JlYyAlPiUKICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKQpgYGAKCk91ciBgZmlwc2AgdmFyaWFibGUgaW5jbHVkZXMgYSBudW1lcmljIGNvZGUgZm9yIHN0YXRlIGFuZCBjb3VudHkgLSBhbmQgdGhlcmVmb3JlIGlzIGVzc2VudGlhbGx5IGEgcHJveHkgZm9yIGNvdW50eS4KU2luY2Ugd2UgYWxyZWFkeSBoYXZlIGNvdW50eSwgd2Ugd2lsbCBqdXN0IHVzZSBpdCBhbmQga2VlcCB0aGUgYGZpcHNgIElEIGFzIGFub3RoZXIgSUQgdmFyaWFibGUuCgpXZSBjYW4gcmVtb3ZlIHRoZSBgZmlwc2AgdmFyaWFibGUgZnJvbSB0aGUgcHJlZGljdG9ycyB1c2luZyBgdXBkYXRlX3JvbGUoKWAgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHJvbGUgaXMgbm8gbG9uZ2VyIGAicHJlZGljdG9yImAuIApXZSBjYW4gbWFrZSB0aGUgcm9sZSBhbnl0aGluZyB3ZSB3YW50IGFjdHVhbGx5LCBzbyB3ZSB3aWxsIGtlZXAgaXQgc29tZXRoaW5nIGlkZW50aWZpYWJsZS4KCmBgYHtyfQpzaW1wbGVfcmVjICU+JQogIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikKYGBgCgpXZSBtaWdodCBhbHNvIHdhbnQgdG8gcmVtb3ZlIHZhcmlhYmxlcyB0aGF0IGFwcGVhciB0byBiZSByZWR1bmRhbnQgYW5kIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIG90aGVycywgYXMgd2Uga25vdyBmcm9tIG91ciBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIHRoYXQgbWFueSBvZiBvdXIgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkIHdpdGggb25lIGFub3RoZXIuIApXZSBjYW4gZG8gdGhpcyB1c2luZyB0aGUgYHN0ZXBfY29ycigpYCBmdW5jdGlvbi4KCldlIGRvbid0IHdhbnQgdG8gcmVtb3ZlIHNvbWUgb2Ygb3VyIHZhcmlhYmxlcywgbGlrZSB0aGUgYENNQVFgIGFuZCBgYW9kYCB2YXJpYWJsZXMsIHdlIGNhbiBzcGVjaWZ5IHRoaXMgdXNpbmcgdGhlIGAtYCBzaWduIGJlZm9yZSB0aGUgbmFtZXMgb2YgdGhlc2UgdmFyaWFibGVzIGxpa2Ugc286CgpgYGB7cn0Kc2ltcGxlX3JlYyAlPiUKICBzdGVwX2NvcnIoYWxsX3ByZWRpY3RvcnMoKSwgLSBDTUFRLCAtIGFvZCkKYGBgCgoKSXQgaXMgYWxzbyBhIGdvb2QgaWRlYSB0byByZW1vdmUgdmFyaWFibGVzIHdpdGggbmVhci16ZXJvIHZhcmlhbmNlLCB3aGljaCBjYW4gYmUgZG9uZSB3aXRoIHRoZSBgc3RlcF9uenYoKWAgZnVuY3Rpb24uIAoKVmFyaWFibGVzIGhhdmUgbG93IHZhcmlhbmNlIGlmIGFsbCB0aGUgdmFsdWVzIGFyZSB2ZXJ5IHNpbWlsYXIsIHRoZSB2YWx1ZXMgYXJlIHZlcnkgc3BhcnNlLCBvciBpZiB0aGV5IGFyZSBoaWdobHkgaW1iYWxhbmNlZC4gQWdhaW4gd2UgZG9uJ3Qgd2FudCB0byByZW1vdmUgb3VyIGBDTUFRYCBhbmQgYGFvZGAgdmFyaWFibGVzLgoKYGBge3J9CnNpbXBsZV9yZWMgJT4lCiAgc3RlcF9uenYoYWxsX3ByZWRpY3RvcnMoKSwgLSBDTUFRLCAtIGFvZCkKYGBgCgo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byBsZWFybiBhYm91dCBleGFtcGxlcyB3aGVyZSB5b3UgbWlnaHQgaGF2ZSBuZWFyLXplcm8gdmFyaWFuY2UgdmFyaWFibGVzPC9zdW1tYXJ5PgoKMSkgKipTaW1pbGFyIFZhbHVlcyoqIC0gSWYgdGhlIHBvcHVsYXRpb24gZGVuc2l0eSB3YXMgbmVhcmx5IHRoZSBzYW1lIGZvciBldmVyeSB6Y3RhIHRoYXQgY29udGFpbmVkIGEgbW9uaXRvciwgdGhlbiBrbm93aW5nIHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgbmVhciBvdXIgbW9uaXRvciB3b3VsZCBjb250cmlidXRlIGxpdHRsZSB0byBvdXIgbW9kZWwgaW4gYXNzaXN0aW5nIHVzIHRvIHByZWRpY3QgbW9uaXRvciBhaXIgcG9sbHV0aW9uIHZhbHVlcy4gCjIpICoqU3BhcnNlIERhdGEqKiAtIElmIGFsbCBvZiB0aGUgbW9uaXRvcnMgd2VyZSBpbiBsb2NhdGlvbnMgd2hlcmUgdGhlIHBvcHVsYXRpb25zIGRpZCBub3QgYXR0ZW5kIGdyYWR1YXRlIHNjaG9vbCwgdGhlbiB0aGVzZSB2YWx1ZXMgd291bGQgbW9zdGx5IGJlIHplcm8sIGFnYWluIHRoaXMgd291bGQgZG8gdmVyeSBsaXR0bGUgdG8gaGVscCB1cyBkaXN0aW5ndWlzaCBvdXIgYWlyIHBvbGx1dGlvbiBtb25pdG9ycy5XaGVuIG1hbnkgb2YgdGhlIHZhbHVlcyBhcmUgemVybyB0aGlzIGlzIGFsc28gY2FsbGVkIHNwYXJzZSBkYXRhLiAgCjMpICoqSW1iYWxhbmNlZCBEYXRhKiogSWYgbmVhcmx5IGFsbCBvZiB0aGUgbW9uaXRvcnMgd2VyZSBsb2NhdGVkIGluIG9uZSBwYXJ0aWN1bGFyIHN0YXRlLCBhbmQgYWxsIHRoZSBvdGhlcnMgb25seSBoYWQgb25lIG1vbml0b3IgZWFjaCwgdGhlbiB0aGUgcmVhbCBwcmVkaWN0aXZlIHZhbHVlIHdvdWxkIHNpbXBseSBiZSBpbiBrbm93aW5nIGlmIGEgbW9uaXRvciBpcyBsb2NhdGVkIGluIHRoYXQgcGFydGljdWxhciBzdGF0ZSBvciBub3QuIEluIHRoaXMgY2FzZSB3ZSBkb24ndCB3YW50IHRvIHJlbW92ZSBvdXIgdmFyaWFibGUsIHdlIGp1c3Qgd2FudCB0byBzaW1wbGlmeSBpdC4KClNlZSB0aGlzIFtibG9nIHBvc3RdKGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL25lYXItemVyby12YXJpYW5jZS1wcmVkaWN0b3JzLXNob3VsZC13ZS1yZW1vdmUtdGhlbS8pe3RhcmdldD0iX2JsYW5rIn0gYWJvdXQgd2h5IHJlbW92aW5nIG5lYXItemVybyB2YXJpYW5jZSB2YXJpYWJsZXMgaXNuJ3QgYWx3YXlzIGEgZ29vZCBpZGVhIGlmIHdlIHRoaW5rIHRoYXQgYSB2YXJpYWJsZSBtaWdodCBiZSBlc3BlY2lhbGx5IGluZm9ybWF0aXZlLgoKPC9kZXRhaWxzPgoKTGV0J3MgcHV0IGFsbCB0aGlzIHRvZ2V0aGVyIG5vdy4gCgoqKlJlbWVtYmVyOiBpdCBpcyBpbXBvcnRhbnQgdG8gYWRkIHRoZSBzdGVwcyB0byB0aGUgcmVjaXBlIGluIGFuIG9yZGVyIHRoYXQgbWFrZXMgc2Vuc2UganVzdCBsaWtlIHdpdGggYSBjb29raW5nIHJlY2lwZS4qKgoKRmlyc3QsIHdlIGFyZSBnb2luZyB0byBjcmVhdGUgbnVtZXJpYyB2YWx1ZXMgZm9yIG91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIHRoZW4gd2Ugd2lsbCBsb29rIGF0IGNvcnJlbGF0aW9uIGFuZCBuZWFyLXplcm8gdmFyaWFuY2UuIApBZ2Fpbiwgd2UgZG8gbm90IHdhbnQgdG8gcmVtb3ZlIHRoZSBgQ01BUWAgYW5kIGBhb2RgIHZhcmlhYmxlcywgc28gd2UgY2FuIG1ha2Ugc3VyZSB0aGV5IGFyZSBrZXB0IGluIHRoZSBtb2RlbCBieSBleGNsdWRpbmcgdGhlbSBmcm9tIHRob3NlIHN0ZXBzLiAKSWYgd2Ugc3BlY2lmaWNhbGx5IHdhbnRlZCB0byByZW1vdmUgYSBwcmVkaWN0b3Igd2UgY291bGQgdXNlIGBzdGVwX3JtKClgLgoKYGBge3J9CnNpbXBsZV9yZWMgJTw+JQogIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lCiAgc3RlcF9kdW1teShzdGF0ZSwgY291bnR5LCBjaXR5LCB6Y3RhLCBvbmVfaG90ID0gVFJVRSkgJT4lCiAgc3RlcF9jb3JyKGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpJT4lCiAgc3RlcF9uenYoYWxsX3ByZWRpY3RvcnMoKSwgLSBDTUFRLCAtIGFvZCkKICAKc2ltcGxlX3JlYwpgYGAKCgoKIyMgUnVubmluZyB0aGUgcHJlLXByb2Nlc3NpbmcKCiMjIyBTdGVwIDE6IFVwZGF0ZSB0aGUgcmVjaXBlIHdpdGggdHJhaW5pbmcgZGF0YSB1c2luZyBgcHJlcCgpYAoKVGhlIG5leHQgbWFqb3IgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlIGlzIGBwcmVwKClgLgpUaGlzIGZ1bmN0aW9uIHVwZGF0ZXMgdGhlIHJlY2lwZSBvYmplY3QgYmFzZWQgb24gdGhlIHRyYWluaW5nIGRhdGEuIApJdCBlc3RpbWF0ZXMgcGFyYW1ldGVycyAoZXN0aW1hdGluZyB0aGUgcmVxdWlyZWQgcXVhbnRpdGllcyBhbmQgc3RhdGlzdGljcyByZXF1aXJlZCBieSB0aGUgc3RlcHMgZm9yIHRoZSB2YXJpYWJsZXMpIGZvciBwcmUtcHJvY2Vzc2luZyBhbmQgdXBkYXRlcyB0aGUgdmFyaWFibGVzIHJvbGVzLCBhcyBzb21lIG9mIHRoZSBwcmVkaWN0b3JzIG1heSBiZSByZW1vdmVkLCB0aGlzIGFsbG93cyB0aGUgcmVjaXBlIHRvIGJlIHJlYWR5IHRvIHVzZSBvbiBvdGhlciBkYXRhIHNldHMuIApJdCAqKmRvZXMgbm90IG5lY2Vzc2FyaWx5IGFjdHVhbGx5IGV4ZWN1dGUgdGhlIHByZS1wcm9jZXNzaW5nIGl0c2VsZioqLCBob3dldmVyIHdlIHdpbGwgc3BlY2lmeSBpbiBhcmd1bWVudCBmb3IgaXQgdG8gZG8gdGhpcyBzbyB0aGF0IHdlIGNhbiB0YWtlIGEgbG9vayBhdCB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhLgoKClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBhcmd1bWVudHMgdG8ga25vdyBhYm91dDoKCjEuIGB0cmFpbmluZ2AgLSB5b3UgbXVzdCBzdXBwbHkgYSB0cmFpbmluZyBkYXRhIHNldCB0byBlc3RpbWF0ZSBwYXJhbWV0ZXJzIGZvciBwcmUtcHJvY2Vzc2luZyBvcGVyYXRpb25zIChyZWNpcGUgc3RlcHMpIC0gdGhpcyBtYXkgYWxyZWFkeSBiZSBpbmNsdWRlZCBpbiB5b3VyIHJlY2lwZSAtIGFzIGlzIHRoZSBjYXNlIGZvciB1cwoyLiBgZnJlc2hgIC0gaWYgYGZyZXNoPVRSVUVgLCAtIHdpbGwgcmV0cmFpbiBhbmQgZXN0aW1hdGUgcGFyYW1ldGVycyBmb3IgYW55IHByZXZpb3VzIHN0ZXBzIHRoYXQgd2VyZSBhbHJlYWR5IHByZXBwZWQgaWYgeW91IGFkZCBtb3JlIHN0ZXBzIHRvIHRoZSByZWNpcGUKMy4gYHZlcmJvc2VgIC0gaWYgYHZlcmJvc2U9VFJVRWAsIHNob3dzIHRoZSBwcm9ncmVzcyBhcyB0aGUgc3RlcHMgYXJlIGV2YWx1YXRlZCBhbmQgdGhlIHNpemUgb2YgdGhlIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgc2V0CjQuIGByZXRhaW5gIC0gaWYgYHJldGFpbj1UUlVFYCwgdGhlbiB0aGUgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBzZXQgd2lsbCBiZSBzYXZlZCB3aXRoaW4gdGhlIHJlY2lwZSAoYXMgdGVtcGxhdGUpLiBUaGlzIGlzIGdvb2QgaWYgeW91IGFyZSBsaWtlbHkgdG8gYWRkIG1vcmUgc3RlcHMgYW5kIGRvIG5vdCB3YW50IHRvIHJlcnVuIHRoZSBgcHJlcCgpYCBvbiB0aGUgcHJldmlvdXMgc3RlcHMuIEhvd2V2ZXIgdGhpcyBjYW4gbWFrZSB0aGUgcmVjaXBlIHNpemUgbGFyZ2UuIFRoaXMgaXMgbmVjZXNzYXJ5IGlmIHlvdSB3YW50IHRvIGFjdHVhbGx5IGxvb2sgYXQgdGhlIHByZS1wcm9jZXNzZWQgZGF0YS4KCkxldCdzIHRyeSBvdXQgdGhlIGBwcmVwKClgIGZ1bmN0aW9uOiAKCmBgYHtyfQpwcmVwcGVkX3JlYyA8LSBwcmVwKHNpbXBsZV9yZWMsIHZlcmJvc2UgPSBUUlVFLCByZXRhaW4gPSBUUlVFICkKbmFtZXMocHJlcHBlZF9yZWMpCmBgYAoKVGhlcmUgYXJlIGFsc28gbG90cyBvZiB1c2VmdWwgdGhpbmdzIHRvIGNoZWNrb3V0IGluIHRoZSBvdXRwdXQgb2YgYHByZXAoKWAuCllvdSBjYW4gc2VlOgoKMS4gdGhlIGBzdGVwc2AgdGhhdCB3ZXJlIHJ1biAgCjIuIHRoZSBvcmlnaW5hbCB2YXJpYWJsZSBpbmZvIChgdmFyX2luZm9gKSAgCjMuIHRoZSB1cGRhdGVkIHZhcmlhYmxlIGluZm8gYWZ0ZXIgcHJlLXByb2Nlc3NpbmcgKGB0ZXJtX2luZm9gKQo0LiB0aGUgbmV3IGBsZXZlbHNgIG9mIHRoZSB2YXJpYWJsZXMgCjUuIHRoZSBvcmlnaW5hbCBsZXZlbHMgb2YgdGhlIHZhcmlhYmxlcyAoYG9yaWdfbHZsc2ApCjYuIGluZm8gYWJvdXQgdGhlIHRyYWluaW5nIGRhdGEgc2V0IHNpemUgYW5kIGNvbXBsZXRlbmVzcyAoYHRyX2luZm9gKQoKKipOb3RlKio6IFlvdSBtYXkgc2VlIHRoZSBgcHJlcC5yZWNpcGUoKWAgZnVuY3Rpb24gaW4gbWF0ZXJpYWwgdGhhdCB5b3UgcmVhZCBhYm91dCB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuIFRoaXMgaXMgcmVmZXJyaW5nIHRvIHRoZSBgcHJlcCgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuCgoKIyMjIFN0ZXAgMjogRXh0cmFjdCBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgdXNpbmcgYGp1aWNlKClgCgpTaW5jZSB3ZSByZXRhaW5lZCBvdXIgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIChpLmUuIGBwcmVwKHJldGFpbj1UUlVFKWApLCB3ZSBjYW4gdGFrZSBhIGxvb2sgYXQgaXQgbGlrZSBieSB1c2luZyB0aGUgYGp1aWNlKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZSBsaWtlIHRoaXM6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInRyYWluaW5nX3ByZXByb2Nlc3NpbmdfcmVjaXBlczMucG5nIikpCmBgYAoKTGV0J3MganVpY2UhIAoKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKanVpY2VkX3RyYWluIDwtIGp1aWNlKHByZXBwZWRfcmVjKQpnbGltcHNlKGp1aWNlZF90cmFpbikKYGBgCiMjIyMKCgpGb3IgZWFzeSBjb21wYXJpc29uIHNha2UgLSBoZXJlIGlzIG91ciBvcmlnaW5hbCBkYXRhOgoKIyMjIyB7LnNjcm9sbGFibGUgfQoKYGBge3J9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKZ2xpbXBzZShwbSkKYGBgCiMjIyMKCk5vdGljZSBob3cgd2Ugb25seSBoYXZlIDM2IHZhcmlhYmxlcyBub3cgaW5zdGVhZCBvZiA1MCEgClR3byBvZiB0aGVzZSBhcmUgb3VyIElEIHZhcmlhYmxlcyAoYGZpcHNgIGFuZCB0aGUgYWN0dWFsIG1vbml0b3IgSUQgKGBpZGApKSBhbmQgb25lIGlzIG91ciBvdXRjb21lIChgdmFsdWVgKS4gClRodXMgd2Ugb25seSBoYXZlIDMzIHByZWRpY3RvcnMgbm93LiAKV2UgY2FuIGFsc28gc2VlIHRoYXQgd2Ugbm8gbG9uZ2VyIGhhdmUgYW55IGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gClZhcmlhYmxlcyBsaWtlIGBzdGF0ZWAgYXJlIGdvbmUgYW5kIG9ubHkgYHN0YXRlX0NhbGlmb3JuaWFgIHJlbWFpbnMgYXMgaXQgd2FzIHRoZSBvbmx5IHN0YXRlIGlkZW50aXR5IHRvIGhhdmUgbm9uemVybyB2YXJpYW5jZS4KV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlcmUgd2VyZSBtb3JlIG1vbml0b3JzIGxpc3RlZCBhcyBgIk5vdCBpbiBhIGNpdHkiYCB0aGFuIGFueSBjaXR5LiAKCldlIGNhbiBzZWUgdGhhdCBDYWxpZm9ybmlhIGhhZCB0aGUgbGFyZ2VzdCBudW1iZXIgb2YgbW9uaXRvcnMgY29tcGFyZWQgdG8gdGhlIG90aGVyIHN0YXRlcy4KCmBgYHtyLCBldmFsID0gRkFMU0V9CnBtICU+JSBjb3VudChzdGF0ZSkgCmBgYAoKClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6CgojIyMjIHsuc2Nyb2xsYWJsZSB9CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpwbSAlPiUgY291bnQoc3RhdGUpICAlPiUKICBwcmludChuID0gMWUzKQpgYGAKCiMjIyMKCmBgYHtyLCBldmFsID0gRkFMU0V9CnBtICU+JSBjb3VudChjaXR5KQpgYGAKClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6CgojIyMjIHsuc2Nyb2xsYWJsZSB9CgpgYGB7ciwgZWNobz1GQUxTRX0KcG0gJT4lIGNvdW50KGNpdHkpICU+JQogIHByaW50KG4gPSAxZTMpCmBgYAoKIyMjIwoKKipOb3RlKio6IFJlY2FsbCB0aGF0IHlvdSBtdXN0IHNwZWNpZnkgYHJldGFpbiA9IFRSVUVgIGFyZ3VtZW50IG9mIHRoZSBgcHJlcCgpYCBmdW5jdGlvbiB0byB1c2UgYGp1aWNlKClgLgoKIyMjIFN0ZXAgMzogRXh0cmFjdCBwcmUtcHJvY2Vzc2VkIHRlc3RpbmcgZGF0YSB1c2luZyBgYmFrZSgpYAoKQWNjb3JkaW5nIHRvIHRoZSBgdGlkeW1vZGVsc2AgZG9jdW1lbnRhdGlvbjoKCj4gYGJha2UoKWAgdGFrZXMgYSB0cmFpbmVkIHJlY2lwZSBhbmQgYXBwbGllcyB0aGUgb3BlcmF0aW9ucyB0byBhIGRhdGEgc2V0IHRvIGNyZWF0ZSBhIGRlc2lnbiBtYXRyaXguCiBGb3IgZXhhbXBsZTogaXQgYXBwbGllcyB0aGUgY2VudGVyaW5nIHRvIG5ldyBkYXRhIHNldHMgdXNpbmcgdGhlc2UgbWVhbnMgdXNlZCB0byBjcmVhdGUgdGhlIHJlY2lwZS4KClRoZXJlZm9yZSwgaWYgeW91IHdhbnRlZCB0byBsb29rIGF0IHRoZSBwcmUtcHJvY2Vzc2VkIHRlc3RpbmcgZGF0YSB5b3Ugd291bGQgdXNlIHRoZSBgYmFrZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuCihZb3UgZ2VuZXJhbGx5IHdhbnQgdG8gbGVhdmUgeW91ciB0ZXN0aW5nIGRhdGEgYWxvbmUsIGJ1dCBpdCBpcyBnb29kIHRvIGxvb2sgZm9yIGlzc3VlcyBsaWtlIHRoZSBpbnRyb2R1Y3Rpb24gb2YgTkEgdmFsdWVzKS4KCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidGVzdGluZ19wcmVwcm9jZXNzaW5nX3JlY2lwZXM0LnBuZyIpKQpgYGAKCkxldCdzIGJha2UhIAoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cix9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKYmFrZWRfdGVzdF9wbSA8LSByZWNpcGVzOjpiYWtlKHByZXBwZWRfcmVjLCBuZXdfZGF0YSA9IHRlc3RfcG0pCmdsaW1wc2UoYmFrZWRfdGVzdF9wbSkKYGBgCiMjIyMKCgpOb3RpY2UgdGhhdCBvdXIgYGNpdHlfTm90LmluLmEuY2l0eWAgdmFyaWFibGUgc2VlbXMgdG8gYmUgTkEgdmFsdWVzLiAKV2h5IG1pZ2h0IHRoYXQgYmU/CgpBaCEgUGVyaGFwcyBpdCBpcyBiZWNhdXNlIHNvbWUgb2Ygb3VyIGxldmVscyB3ZXJlIG5vdCBwcmV2aW91c2x5IHNlZW4gaW4gdGhlIHRyYWluaW5nIHNldCEKCkxldCdzIHRha2UgYSBsb29rIHVzaW5nIHRoZSBbc2V0IG9wZXJhdGlvbnNdKGh0dHBzOi8vd3d3LnByb2JhYmlsaXR5Y291cnNlLmNvbS9jaGFwdGVyMS8xXzJfMl9zZXRfb3BlcmF0aW9ucy5waHApe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gCldlIGNhbiB0YWtlIGEgbG9vayBhdCBjaXRpZXMgdGhhdCB3ZXJlIGRpZmZlcmVudCBiZXR3ZWVuIHRoZSB0ZXN0IGFuZCB0cmFpbmluZyBzZXQuCgpgYGB7cn0KdHJhaW5jaXRpZXMgPC0gdHJhaW5fcG0gJT4lIGRpc3RpbmN0KGNpdHkpCnRlc3RjaXRpZXMgPC0gdGVzdF9wbSAlPiUgZGlzdGluY3QoY2l0eSkKCiNnZXQgdGhlIG51bWJlciBvZiBjaXRpZXMgdGhhdCB3ZXJlIGRpZmZlcmVudApkaW0oZHBseXI6OnNldGRpZmYodHJhaW5jaXRpZXMsIHRlc3RjaXRpZXMpKQoKI2dldCB0aGUgbnVtYmVyIG9mIGNpdGllcyB0aGF0IG92ZXJsYXBwZWQKZGltKGRwbHlyOjppbnRlcnNlY3QodHJhaW5jaXRpZXMsIHRlc3RjaXRpZXMpKQpgYGAKCkluZGVlZCwgdGhlcmUgYXJlIGxvdHMgb2YgZGlmZmVyZW50IGNpdGllcyBpbiBvdXIgdGVzdCBkYXRhIHRoYXQgYXJlIG5vdCBpbiBvdXIgdHJhaW5pbmcgZGF0YSEKCgpTbywgbGV0IGdvIGJhY2sgdG8gb3VyIGBwbWAgZGF0YSBzZXQgYW5kIG1vZGlmeSB0aGUgYGNpdHlgIHZhcmlhYmxlIHRvIGp1c3QgYmUgdmFsdWVzIG9mIGBpbiBhIGNpdHlgIG9yIGBub3QgaW4gYSBjaXR5YCB1c2luZyB0aGUgYGNhc2Vfd2hlbigpYCBmdW5jdGlvbiBvZiBgZHBseXJgLgpUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gdmVjdG9yaXplIG11bHRpcGxlIGBpZl9lbHNlKClgIHN0YXRlbWVudHMuCgpgYGB7cn0KcG0gJT4lCiAgbXV0YXRlKGNpdHkgPSBjYXNlX3doZW4oY2l0eSA9PSAiTm90IGluIGEgY2l0eSIgfiAiTm90IGluIGEgY2l0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2l0eSAhPSAiTm90IGluIGEgY2l0eSIgfiAiSW4gYSBjaXR5IikpCmBgYAoKQWx0ZXJuYXRpdmVseSB5b3UgY291bGQgY3JlYXRlIGEgW2N1c3RvbSBzdGVwIGZ1bmN0aW9uXShodHRwczovL3JlY2lwZXMudGlkeW1vZGVscy5vcmcvYXJ0aWNsZXMvQ3VzdG9tX1N0ZXBzLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gdG8gZG8gdGhpcyBhbmQgYWRkIHRoaXMgdG8geW91ciByZWNpcGUsIGJ1dCB0aGF0IGlzIGJleW9uZCB0aGUgc2NvcGUgb2YgdGhpcyBjYXNlIHN0dWR5LiAKCldlIHdpbGwgbmVlZCB0byByZXBlYXQgYWxsIHRoZSBzdGVwcyAoc3BsaXR0aW5nIHRoZSBkYXRhLCBwcmUtcHJvY2Vzc2luZywgZXRjKSBhcyB0aGUgbGV2ZWxzIG9mIG91ciB2YXJpYWJsZXMgaGF2ZSBub3cgY2hhbmdlZC4gCgpXaGlsZSB3ZSBhcmUgZG9pbmcgdGhpcywgd2UgbWlnaHQgYWxzbyBoYXZlIHRoaXMgaXNzdWUgZm9yIGBjb3VudHlgLiAKClRoZSBgY291bnR5YCB2YXJpYWJsZXMgYXBwZWFycyB0byBnZXQgZHJvcHBlZCBkdWUgdG8gZWl0aGVyIGNvcnJlbGF0aW9uIG9yIG5lYXIgemVybyB2YXJpYW5jZS4gCgpJdCBpcyBsaWtlbHkgZHVlIHRvIG5lYXIgemVybyB2YXJpYW5jZSBiZWNhdXNlIHRoaXMgaXMgdGhlIG1vcmUgZ3JhbnVsYXIgb2YgdGhlc2UgZ2VvZ3JhcGhpYyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYW5kIGxpa2VseSBzcGFyc2UuCgpgYGB7cn0KcG0gJTw+JQogIG11dGF0ZShjaXR5ID0gY2FzZV93aGVuKGNpdHkgPT0gIk5vdCBpbiBhIGNpdHkiIH4gIk5vdCBpbiBhIGNpdHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNpdHkgIT0gIk5vdCBpbiBhIGNpdHkiIH4gIkluIGEgY2l0eSIpKQoKc2V0LnNlZWQoMTIzNCkgIyBzYW1lIHNlZWQgYXMgYmVmb3JlCnBtX3NwbGl0IDwtcnNhbXBsZTo6aW5pdGlhbF9zcGxpdChkYXRhID0gcG0sIHByb3AgPSAyLzMpCnBtX3NwbGl0CiB0cmFpbl9wbSA8LXJzYW1wbGU6OnRyYWluaW5nKHBtX3NwbGl0KQogdGVzdF9wbSA8LXJzYW1wbGU6OnRlc3RpbmcocG1fc3BsaXQpCmBgYAoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpTZWUgaWYgeW91IGNhbiBjb21lIHVwIHdpdGggdGhlIGNvZGUgZm9yIHRoZSBuZXcgcmVjaXBlLgoKIyMjIwoKKioqCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBjb2RlIGZvciB0aGUgbmV3IHJlY2lwZS4gPC9zdW1tYXJ5PgoKCmBgYHtyfQpub3ZlbF9yZWMgPC1yZWNpcGUodHJhaW5fcG0pICU+JQogICAgdXBkYXRlX3JvbGUoZXZlcnl0aGluZygpLCBuZXdfcm9sZSA9ICJwcmVkaWN0b3IiKSAlPiUKICAgIHVwZGF0ZV9yb2xlKHZhbHVlLCBuZXdfcm9sZSA9ICJvdXRjb21lIikgJT4lCiAgICB1cGRhdGVfcm9sZShpZCwgbmV3X3JvbGUgPSAiaWQgdmFyaWFibGUiKSAlPiUKICAgIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lCiAgICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKSAlPiUKICAgIHN0ZXBfY29ycihhbGxfbnVtZXJpYygpKSAlPiUKICAgIHN0ZXBfbnp2KGFsbF9udW1lcmljKCkpIApgYGAKPC9kZXRhaWxzPgoqKioKCmBgYHtyfQpub3ZlbF9yZWMKYGBgCgoKCk5vdyBsZXQncyByZXRyYWluIG91ciB0cmFpbmluZyBkYXRhIGFuZCB0cnkgYmFraW5nIG91ciB0ZXN0IGRhdGEuCgoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpEbyB5b3UgcmVjYWxsIGhvdyB0byBwcmUtcHJvY2VzcyBhbmQgZXh0cmFjdCB0aGUgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhPwoKIyMjIwoKKioqCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4KCmBgYHtyfQpwcmVwcGVkX3JlYyA8LSBwcmVwKG5vdmVsX3JlYywgdmVyYm9zZSA9IFRSVUUsIHJldGFpbiA9IFRSVUUpCmp1aWNlZF90cmFpbiA8LSBqdWljZShwcmVwcGVkX3JlYykKYGBgCjwvZGV0YWlscz4gCioqKgoKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKZ2xpbXBzZShqdWljZWRfdHJhaW4pCmBgYAoKIyMjIwoKQW5kIG5vdywgbGV0J3MgdHJ5IGJha2luZyBvdXIgdGVzdCBzZXQgdG8gc2VlIGlmIHdlIHN0aWxsIGhhdmUgYE5BYCB2YWx1ZXMuCgojIyMjIHsuc2Nyb2xsYWJsZSB9CgpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpiYWtlZF90ZXN0X3BtIDwtIHJlY2lwZXM6OmJha2UocHJlcHBlZF9yZWMsIG5ld19kYXRhID0gdGVzdF9wbSkKCmdsaW1wc2UoYmFrZWRfdGVzdF9wbSkKYGBgCgojIyMjCgpHcmVhdCwgbm93IHdlIG5vIGxvbmdlciBoYXZlIGBOQWAgdmFsdWVzISA6KQoKKipOb3RlKio6IGlmIHlvdSB1c2UgdGhlIHNraXAgb3B0aW9uIGZvciBzb21lIG9mIHRoZSBwcmUtcHJvY2Vzc2luZyBzdGVwcywgYmUgY2FyZWZ1bC4gCmBqdWljZSgpYCB3aWxsIHNob3cgYWxsIG9mIHRoZSByZXN1bHRzIGlnbm9yaW5nIGBza2lwID0gVFJVRWAuIApgYmFrZSgpYCB3aWxsIG5vdCBuZWNlc3NhcmlseSBjb25kdWN0IHRoZXNlIHN0ZXBzIG9uIHRoZSBuZXcgZGF0YS4KCgojIyBTcGVjaWZ5aW5nIHRoZSBtb2RlbAoKU28gZmFyIHdlIGhhdmUgdXNlZCB0aGUgcGFja2FnZXMgYHJzYW1wbGVgIHRvIHNwbGl0IHRoZSBkYXRhIGFuZCBgcmVjaXBlc2AgdG8gYXNzaWduIHZhcmlhYmxlIHR5cGVzLCBhbmQgdG8gc3BlY2lmeSBhbmQgcHJlcCBvdXIgcHJlLXByb2Nlc3NpbmcgKGFzIHdlbGwgYXMgdG8gb3B0aW9uYWxseSBleHRyYWN0IHRoZSBwcmUtcHJvY2Vzc2VkIGRhdGEpLgoKV2Ugd2lsbCBub3cgdXNlIHRoZSBgcGFyc25pcGAgcGFja2FnZSAod2hpY2ggaXMgc2ltaWxhciB0byB0aGUgcHJldmlvdXMgYGNhcmV0YCBwYWNrYWdlIC0gYW5kIGhlbmNlIHdoeSBpdCBpcyBuYW1lZCBhZnRlciB0aGUgdmVnZXRhYmxlKSB0byBzcGVjaWZ5IG91ciBtb2RlbC4KClRoZXJlIGFyZSBmb3VyIHRoaW5ncyB3ZSBuZWVkIHRvIGRlZmluZSBhYm91dCBvdXIgbW9kZWw6ICAKCjEuIFRoZSAqKnR5cGUqKiBvZiBtb2RlbCAodXNpbmcgc3BlY2lmaWMgZnVuY3Rpb25zIGluIHBhcnNuaXAgbGlrZSBgcmFuZF9mb3Jlc3QoKWAsIGBsb2dpc3RpY19yZWcoKWAgZXRjLikgIAoyLiBUaGUgcGFja2FnZSBvciAqKmVuZ2luZSoqIHRoYXQgd2Ugd2lsbCB1c2UgdG8gaW1wbGVtZW50IHRoZSB0eXBlIG9mIG1vZGVsIHNlbGVjdGVkICh1c2luZyB0aGUgYHNldF9lbmdpbmUoKWAgZnVuY3Rpb24pIAozLiBUaGUgKiptb2RlKiogb2YgbGVhcm5pbmcgLSBjbGFzc2lmaWNhdGlvbiBvciByZWdyZXNzaW9uICh1c2luZyB0aGUgYHNldF9tb2RlKClgIGZ1bmN0aW9uKSAKNC4gQW55ICoqYXJndW1lbnRzKiogbmVjZXNzYXJ5IGZvciB0aGUgbW9kZWwvcGFja2FnZSBzZWxlY3RlZCAodXNpbmcgdGhlIGBzZXRfYXJncygpYGZ1bmN0aW9uIC0gIGZvciBleGFtcGxlIHRoZSBgbXRyeSA9YCBhcmd1bWVudCBmb3IgcmFuZG9tIGZvcmVzdCB3aGljaCBpcyB0aGUgbnVtYmVyIG9mIHZhcmlhYmxlcyB0byBiZSB1c2VkIGFzIG9wdGlvbnMgZm9yIHNwbGl0dGluZyBhdCBlYWNoIHRyZWUgbm9kZSkKCkxldCdzIHdhbGsgdGhyb3VnaCB0aGVzZSBzdGVwcyBvbmUgYnkgb25lLiAKRm9yIG91ciBjYXNlLCB3ZSBhcmUgZ29pbmcgdG8gc3RhcnQgb3VyIGFuYWx5c2lzIHdpdGggYSBsaW5lYXIgcmVncmVzc2lvbiBidXQgd2Ugd2lsbCBkZW1vbnN0cmF0ZSBob3cgd2UgY2FuIHRyeSBkaWZmZXJlbnQgbW9kZWxzLgoKVGhlIGZpcnN0IHN0ZXAgaXMgdG8gZGVmaW5lIHdoYXQgdHlwZSBvZiBtb2RlbCB3ZSB3b3VsZCBsaWtlIHRvIHVzZS4gClNlZSBbaGVyZV0oaHR0cHM6Ly93d3cudGlkeW1vZGVscy5vcmcvZmluZC9wYXJzbmlwLyl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9kZWxpbmcgb3B0aW9ucyBpbiBgcGFyc25pcGAuCgoKYGBge3J9ClBNX21vZGVsIDwtIHBhcnNuaXA6OmxpbmVhcl9yZWcoKSAjIFBNIHdhcyB1c2VkIGluIHRoZSBuYW1lIGZvciBwYXJ0aWN1bGF0ZSBtYXR0ZXIKUE1fbW9kZWwKYGBgCgpPSy4gU28gZmFyLCBhbGwgd2UgaGF2ZSBkZWZpbmVkIGlzIHRoYXQgd2Ugd2FudCB0byB1c2UgYSBsaW5lYXIgcmVncmVzc2lvbi4uLiAgCkxldCdzIHRlbGwgYHBhcnNuaXBgIG1vcmUgYWJvdXQgd2hhdCB3ZSB3YW50LgoKV2Ugd291bGQgbGlrZSB0byB1c2UgdGhlIFtvcmRpbmFyeSBsZWFzdCBzcXVhcmVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9PcmRpbmFyeV9sZWFzdF9zcXVhcmVzKSBtZXRob2QgdG8gZml0IG91ciBsaW5lYXIgcmVncmVzc2lvbi4gClNvIHdlIHdpbGwgdGVsbCBgcGFyc25pcGAgdGhhdCB3ZSB3YW50IHRvIHVzZSB0aGUgYGxtYCBwYWNrYWdlIHRvIGltcGxlbWVudCBvdXIgbGluZWFyIHJlZ3Jlc3Npb24gKHRoZXJlIGFyZSBtYW55IG9wdGlvbnMgYWN0dWFsbHkgc3VjaCBhcyBbYHJzdGFuYF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JzdGFuL3ZpZ25ldHRlcy9yc3Rhbi5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICBbYGdsbW5ldGBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nbG1uZXQvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSwgW2BrZXJhc2BdKGh0dHBzOi8va2VyYXMucnN0dWRpby5jb20vKXt0YXJnZXQ9Il9ibGFuayJ9LCBhbmQgW2BzcGFya2x5cmBdKGh0dHBzOi8vdGhlcmluc3BhcmsuY29tL3N0YXJ0aW5nLmh0bWwjc3RhcnRpbmctc3BhcmtseXItaGVsbG8td29ybGQpe3RhcmdldD0iX2JsYW5rIn0pLiBTZWUgW2hlcmVdKGh0dHBzOi8vcGFyc25pcC50aWR5bW9kZWxzLm9yZy9yZWZlcmVuY2UvbGluZWFyX3JlZy5odG1sKSBmb3IgYSBkZXNjcmlwdGlvbiBvZiB0aGUgZGlmZmVyZW5jZXMgYW5kIHVzaW5nIHRoZXNlIGRpZmZlcmVudCBlbmdpbmVzIHdpdGggYHBhcnNuaXBgLgoKV2Ugd2lsbCBkbyBzbyBieSB1c2luZyB0aGUgYHNldF9lbmdpbmUoKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlLgoKYGBge3J9CmxtX1BNX21vZGVsIDwtIAogIFBNX21vZGVsICAlPiUKICBwYXJzbmlwOjpzZXRfZW5naW5lKCJsbSIpCgpsbV9QTV9tb2RlbApgYGAKCkluIHNvbWUgY2FzZXMgc29tZSBwYWNrYWdlcyBjYW4gZG8gZWl0aGVyIGNsYXNzaWZpY2F0aW9uIG9yIHByZWRpY3Rpb24sIHNvIGl0IGlzIGEgZ29vZCBpZGVhIHRvIHNwZWNpZnkgd2hpY2ggbW9kZSB5b3UgaW50ZW5kIHRvIHBlcmZvcm0uIApIZXJlLCB3ZSBhaW0gdG8gcHJlZGljdCB0aGUgYWlyIHBvbGx1dGlvbi4gCllvdSBjYW4gZG8gdGhpcyB3aXRoIHRoZSBgc2V0X21vZGUoKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlLCBieSB1c2luZyBlaXRoZXIgYHNldF9tb2RlKCJjbGFzc2lmaWNhdGlvbiIpYCBvciBgc2V0X21vZGUoInJlZ3Jlc3Npb24iKWAuCgpgYGB7cn0KbG1fUE1fbW9kZWwgPC0gCiAgUE1fbW9kZWwgICU+JQogIHBhcnNuaXA6OnNldF9lbmdpbmUoImxtIikgJT4lCiAgc2V0X21vZGUoInJlZ3Jlc3Npb24iKQoKbG1fUE1fbW9kZWwKYGBgCgojIyBGaXR0aW5nIHRoZSBtb2RlbAoKV2UgY2FuICB1c2UgdGhlIGBwYXJzbmlwYCBwYWNrYWdlIHdpdGggYSBuZXdlciBwYWNrYWdlIGNhbGxlZCBgd29ya2Zsb3dzYCB0byBmaXQgb3VyIG1vZGVsLiAKClRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlIGFsbG93cyB1cyB0byBrZWVwIHRyYWNrIG9mIGJvdGggb3VyIHByZS1wcm9jZXNzaW5nIHN0ZXBzIGFuZCBvdXIgbW9kZWwgc3BlY2lmaWNhdGlvbi4gSXQgYWxzbyBhbGxvd3MgdXMgdG8gaW1wbGVtZW50IGZhbmNpZXIgb3B0aW1pemF0aW9ucyBpbiBhbiBhdXRvbWF0ZWQgd2F5IGFuZCBpdCBjYW4gYWxzbyBoYW5kbGUgcG9zdC1wcm9jZXNzaW5nIG9wZXJhdGlvbnMuIAoKCldlIGJlZ2luIGJ5IGNyZWF0aW5nIGEgd29ya2Zsb3cgdXNpbmcgdGhlIGB3b3JrZmxvdygpYCBmdW5jdGlvbiBpbiB0aGUgYHdvcmtmbG93c2AgcGFja2FnZS4gCgpOZXh0LCB3ZSB1c2UgYGFkZF9yZWNpcGUoKWAgKG91ciBwcmUtcHJvY2Vzc2luZyBzcGVjaWZpY2F0aW9ucykgYW5kIHdlIGFkZCBvdXIgbW9kZWwgd2l0aCB0aGUgYGFkZF9tb2RlbCgpYCBmdW5jdGlvbiAtLSBib3RoIGZ1bmN0aW9ucyBmcm9tIHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlLgoKKipOb3RlKio6IFdlIGRvIG5vdCBuZWVkIHRvIGFjdHVhbGx5IGBwcmVwKClgIG91ciByZWNpcGUgYmVmb3JlIHVzaW5nIHdvcmtmbG93cyEKCklmIHlvdSByZWNhbGwgYG5vdmVsX3JlY2AgaXMgdGhlIHJlY2lwZSB3ZSBwcmV2aW91c2x5IGNyZWF0ZWQgd2l0aCB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgYW5kIGBsbV9QTV9tb2RlbGAgd2FzIGNyZWF0ZWQgd2hlbiB3ZSBzcGVjaWZpZWQgb3VyIG1vZGVsIHdpdGggdGhlIGBwYXJzbmlwYCBwYWNrYWdlLgpIZXJlLCB3ZSBjb21iaW5lIGV2ZXJ5dGhpbmcgdG9nZXRoZXIgaW50byBhIHdvcmtmbG93LiAKCmBgYHtyfQpQTV93ZmxvdyA8LXdvcmtmbG93czo6d29ya2Zsb3coKSAlPiUKICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUobm92ZWxfcmVjKSAlPiUKICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9tb2RlbChsbV9QTV9tb2RlbCkKUE1fd2Zsb3cKYGBgCgpBaCwgbmljZS4gCk5vdGljZSBob3cgaXQgdGVsbHMgdXMgYWJvdXQgYm90aCBvdXIgcHJlLXByb2Nlc3Npbmcgc3RlcHMgYW5kIG91ciBtb2RlbCBzcGVjaWZpY2F0aW9ucy4KCk5leHQsIHdlICJwcmVwYXJlIHRoZSByZWNpcGUiIChvciBlc3RpbWF0ZSB0aGUgcGFyYW1ldGVycykgYW5kIGZpdCB0aGUgbW9kZWwgdG8gb3VyIHRyYWluaW5nIGRhdGEgYWxsIGF0IG9uY2UuIApQcmludGluZyB0aGUgb3V0cHV0LCB3ZSBjYW4gc2VlIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIG1vZGVsLgoKYGBge3J9ClBNX3dmbG93X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUE1fd2Zsb3csIGRhdGEgPSB0cmFpbl9wbSkKUE1fd2Zsb3dfZml0CmBgYAoKCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHNlZSB0aGUgc3RlcHMgdGhhdCB0aGUgYHdvcmtmbG93c2AgcGFja2FnZSBwZXJmb3JtcyB0aGF0IHVzZWQgdG8gYmUgcmVxdWlyZWQgPC9zdW1tYXJ5PgoKUHJldmlvdXNseSwgdGhlIHByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIChganVpY2VkX3RyYWluYCksIGFzIG9wcG9zZWQgdG8gdGhlIHJhdyB0cmFpbmluZyBkYXRhLCB3b3VsZCBiZSByZXF1aXJlZCB0byBmaXQgdGhlIG1vZGVsLgoKSW4gdGhpcyBjYXNlLCB3ZSB3b3VsZCBhY3R1YWxseSBhbHNvIG5lZWQgdG8gd3JpdGUgdGhlIG1vZGVsIGFnYWluISAKUmVjYWxsIHRoYXQgYGlkYCBhbmQgYGZpcHNgIGFyZSBJRCB2YXJpYWJsZXMgYW5kIHRoYXQgYHZhbHVlc2AgaXMgb3VyIG91dGNvbWUgb2YgaW50ZXJlc3QgKHRoZSBhaXIgcG9sbHV0aW9uIG1lYXN1cmUgYXQgZWFjaCBtb25pdG9yKS4gSXQgaXMgbmljZSB0aGF0IGB3b3JrZmxvd3NgIGtlZXBzIHRyYWNrIG9mIHRoaXMhCgpgYGB7cn0KanVpY2VkX3RyYWluX3JlYWR5IDwtIGp1aWNlZF90cmFpbiAlPiUgCiAgc2VsZWN0KC1pZCwgLWZpcHMpCgpQTV9maXQgPC0gbG1fUE1fbW9kZWwgJT4lIAogIHBhcnNuaXA6OmZpdCh2YWx1ZSB+LiwgZGF0YSA9IGp1aWNlZF90cmFpbl9yZWFkeSkKYGBgCgo8L2RldGFpbHM+CgojIyBBc3Nlc3NpbmcgdGhlIG1vZGVsIGZpdAoKQWZ0ZXIgd2UgZml0IG91ciBtb2RlbCwgd2UgY2FuIHVzZSB0aGUgYGJyb29tYCBwYWNrYWdlIHRvIGxvb2sgYXQgdGhlIG91dHB1dCBmcm9tIHRoZSBmaXR0ZWQgbW9kZWwgaW4gYW4gZWFzeS90aWR5IHdheS4gICAKClRoZSBgdGlkeSgpYCBmdW5jdGlvbiByZXR1cm5zIGEgdGlkeSBkYXRhIGZyYW1lIHdpdGggY29lZmZpY2llbnRzIGZyb20gdGhlIG1vZGVsIChvbmUgcm93IHBlciBjb2VmZmljaWVudCkuCgpNYW55IG90aGVyIGBicm9vbWAgZnVuY3Rpb25zIGN1cnJlbnRseSBvbmx5IHdvcmsgd2l0aCBgcGFyc25pcGAgb2JqZWN0cywgbm90IHJhdyBgd29ya2Zsb3dzYCBvYmplY3RzLiAKCkhvd2V2ZXIsIHdlIGNhbiB1c2UgdGhlIGB0aWR5YCBmdW5jdGlvbiBpZiB3ZSBmaXJzdCB1c2UgdGhlIGBwdWxsX3dvcmtmbG93X2ZpdCgpYCBmdW5jdGlvbi4KCmBgYHtyfQp3Zmxvd291dHB1dCA8LSBQTV93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIGJyb29tOjp0aWR5KCkgCmBgYAoKCmBgYHtyfQp3Zmxvd291dHB1dApgYGAKCldlIGhhdmUgZml0IG91ciBtb2RlbCBvbiBvdXIgdHJhaW5pbmcgZGF0YSwgd2hpY2ggbWVhbnMgd2UgaGF2ZSBjcmVhdGVkIGEgbW9kZWwgdG8gcHJlZGljdCB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbiBiYXNlZCBvbiB0aGUgcHJlZGljdG9ycyB0aGF0IHdlIGhhdmUgaW5jbHVkZWQuIFlheSEKCk9uZSBsYXN0IHRoaW5nIGJlZm9yZSB3ZSBsZWF2ZSB0aGlzIHNlY3Rpb24uIApXZSBvZnRlbiBhcmUgaW50ZXJlc3RlZCBpbiBnZXR0aW5nIGEgc2Vuc2Ugb2Ygd2hpY2ggdmFyaWFibGVzIGFyZSB0aGUgbW9zdCBpbXBvcnRhbnQgaW4gb3VyIG1vZGVsLiAKV2UgY2FuIGV4cGxvcmUgdGhlIHZhcmlhYmxlIGltcG9ydGFuY2UgdXNpbmcgdGhlIGB2aXAoKWAgZnVuY3Rpb24gb2YgdGhlIGB2aXBgIHBhY2thZ2UuIApUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgYSBiYXIgcGxvdCBvZiB2YXJpYWJsZSBpbXBvcnRhbmNlIHNjb3JlcyBmb3IgZWFjaCBwcmVkaWN0b3IgdmFyaWFibGUgKG9yIGZlYXR1cmUpIGluIGEgbW9kZWwuIApUaGUgYmFyIHBsb3QgaXMgb3JkZXJlZCBieSBpbXBvcnRhbmNlIChoaWdoZXN0IHRvIHNtYWxsZXN0KS4gCgoKTm90aWNlIGFnYWluIHRoYXQgd2UgbmVlZCB0byB1c2UgdGhlIGBwdWxsX3dvcmtmbG93X2ZpdCgpYCBmdW5jdGlvbi4KCkxldCdzIHRha2UgYSBsb29rIGF0IHRoZSB0b3AgMTAgY29udHJpYnV0aW5nIHZhcmlhYmxlczoKCmBgYHtyfQpQTV93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIHZpcChudW1fZmVhdHVyZXMgPSAxMCkKYGBgCgpUaGUgc3RhdGUgaW4gd2hpY2ggdGhlIG1vbml0b3Igd2FzIGxvY2F0ZWQgYW5kIHRoZSBDTUFRIG1vZGVsIGFuZCB0aGUgYW9kIHNhdGVsbGl0ZSBpbmZvcm1hdGlvbiBhcHBlYXIgdG8gYmUgdGhlIG1vc3QgaW1wb3J0YW50IGZvciBwcmVkaWN0aW5nIHRoZSBhaXIgcG9sbHV0aW9uIGF0IGEgZ2l2ZW4gbW9uaXRvci4KCiMjIE1vZGVsIHBlcmZvcm1hbmNlCgpJbiB0aGlzIG5leHQgc2VjdGlvbiwgb3VyIGdvYWwgaXMgdG8gYXNzZXNzIHRoZSBvdmVyYWxsIG1vZGVsIHBlcmZvcm1hbmNlLiAKVGhlIHdheSB3ZSBkbyB0aGlzIGlzIHRvIGNvbXBhcmUgdGhlIHNpbWlsYXJpdHkgYmV0d2VlbiB0aGUgcHJlZGljdGVkIGVzdGltYXRlcyBvZiB0aGUgb3V0Y29tZSB2YXJpYWJsZSBwcm9kdWNlZCBieSB0aGUgbW9kZWwgYW5kIHRoZSB0cnVlIG91dGNvbWUgdmFyaWFibGUgdmFsdWVzLiAKCklmIHlvdSByZWNhbGwgdGhlIFtXaGF0IGlzIG1hY2hpbmUgbGVhcm5pbmc/XSgjd2hhdGlzbWwpIHNlY3Rpb24sIHdlIHNob3dlZCBob3cgdG8gdGhpbmsgYWJvdXQgbWFjaGluZSBsZWFybmluZyAoTUwpIGFzIGFuIG9wdGltaXphdGlvbiBwcm9ibGVtIHRoYXQgdHJpZXMgdG8gbWluaW1pemUgdGhlIGRpc3RhbmNlIGJldHdlZW4gb3VyIHByZWRpY3RlZCBvdXRjb21lICRcaGF0e1l9ID0gZihYKSQgYW5kIGFjdHVhbCBvdXRjb21lICRZJCB1c2luZyBvdXIgZmVhdHVyZXMgKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpICRYJCBhcyBpbnB1dCB0byBhIGZ1bmN0aW9uICRmJCB0aGF0IHdlIHdhbnQgdG8gZXN0aW1hdGUuIAoKJCRkKFkgLSBcaGF0e1l9KSQkCgpBcyBvdXIgZ29hbCBpbiB0aGlzIHNlY3Rpb24gaXMgdG8gYXNzZXNzIG92ZXJhbGwgbW9kZWwgcGVyZm9ybWFuY2UsIHdlIHdpbGwgbm93IHRhbGsgYWJvdXQgZGlmZmVyZW50IGRpc3RhbmNlIG1ldHJpY3MgdGhhdCB5b3UgY2FuIHVzZS4gCgpGaXJzdCwgbGV0J3MgcHVsbCBvdXQgb3VyIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyAkXGhhdHtZfSA9IGYoWCkkIGZyb20gdGhlIG1vZGVscyB3ZSBmaXQgKHVzaW5nIGRpZmZlcmVudCBhcHByb2FjaGVzKS4gCgoKYGBge3J9CndmX2ZpdCA8LSBQTV93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkKCndmX2ZpdHRlZF92YWx1ZXMgPC0gZml0dGVkKHdmX2ZpdFtbImZpdCJdXSkKaGVhZCh3Zl9maXR0ZWRfdmFsdWVzKQpgYGAKCkFsdGVybmF0aXZlbHksIHdlIGNhbiBnZXQgdGhlIGZpdHRlZCB2YWx1ZXMgdXNpbmcgdGhlIGBhdWdtZW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgYnJvb21gIHBhY2thZ2UgdXNpbmcgdGhlIG91dHB1dCBmcm9tIGB3b3JrZmxvd3NgOiAKCmBgYHtyfQp3Zl9maXR0ZWRfdmFsdWVzIDwtIAogIGJyb29tOjphdWdtZW50KHdmX2ZpdFtbImZpdCJdXSwgZGF0YSA9IGp1aWNlZF90cmFpbikgJT4lIAogIHNlbGVjdCh2YWx1ZSwgLmZpdHRlZDouc3RkLnJlc2lkKQoKaGVhZCh3Zl9maXR0ZWRfdmFsdWVzKQoKYGBgCgpOb3RlIHRoYXQgYmVjdWFzZSB3ZSB1c2UgdGhlIGFjdHVhbCB3b3JrZmxvdyBoZXJlLCB3ZSBjYW4gKGFuZCBhY3R1YWxseSBuZWVkIHRvKSB1c2UgdGhlIHJhdyBkYXRhIGluc3RlYWQgb2YgdGhlIHByZS1wcm9jZXNzZWQgZGF0YS4KCmBgYHtyfQp2YWx1ZXNfcHJlZF90cmFpbiA8LSAKICBwcmVkaWN0KFBNX3dmbG93X2ZpdCwgdHJhaW5fcG0pICU+JSAKICBiaW5kX2NvbHModHJhaW5fcG0gJT4lIHNlbGVjdCh2YWx1ZSwgZmlwcywgY291bnR5LCBpZCkpIAoKdmFsdWVzX3ByZWRfdHJhaW4KCmBgYAoKIyMjIFZpc3VhbGl6aW5nIG1vZGVsIHBlcmZvcm1hbmNlCgpOb3csIHdlIGNhbiBjb21wYXJlIHRoZSBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgKG9yIGZpdHRlZCB2YWx1ZXMpICRcaGF0e1l9JCB0byB0aGUgYWN0dWFsIG91dGNvbWUgdmFsdWVzICRZJCB0aGF0IHdlIG9ic2VydmVkOiAKCmBgYHtyfQp3Zl9maXR0ZWRfdmFsdWVzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSAgdmFsdWUsIHkgPSAuZml0dGVkKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICB4bGFiKCJhY3R1YWwgb3V0Y29tZSB2YWx1ZXMiKSArIAogIHlsYWIoInByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyIpCmBgYAoKT0ssIHNvIG91ciByYW5nZSBvZiB0aGUgcHJlZGljdGVkIG91dGNvbWUgdmFsdWVzIGFwcGVhcnMgdG8gYmUgc21hbGxlciB0aGFuIHRoZSByZWFsIHZhbHVlcy4gCldlIGNvdWxkIHByb2JhYmx5IGRvIGEgYml0IGJldHRlci4KCiMjIyBRdWFudGlmeWluZyBtb2RlbCBwZXJmb3JtYW5jZSAKCk5leHQsIGxldCdzIHVzZSBkaWZmZXJlbnQgZGlzdGFuY2UgZnVuY3Rpb25zICRkKFxjZG90KSQgdG8gYXNzZXNzIGhvdyBmYXIgb2ZmIG91ciBwcmVkaWN0ZWQgb3V0Y29tZSAkXGhhdHtZfSA9IGYoWCkkIGFuZCBhY3R1YWwgb3V0Y29tZSAkWSQgdmFsdWVzIGFyZSBmcm9tIGVhY2ggb3RoZXI6IAoKJCRkKFkgLSBcaGF0e1l9KSQkCgpBcyBtZW50aW9uZWQsIHRoZXJlIGFyZSBlbnRpcmUgc2Nob2xhcmx5IGZpZWxkcyBvZiByZXNlYXJjaCBkZWRpY2F0ZWQgdG8gaWRlbnRpZnlpbmcgZGlmZmVyZW50IGRpc3RhbmNlIG1ldHJpY3MgJGQoXGNkb3QpJCBmb3IgbWFjaGluZSBsZWFybmluZyBhcHBsaWNhdGlvbnMuIApIb3dldmVyLCB3aGVuIHBlcmZvcm1pbmcgcHJlZGljdGlvbiB3aXRoIGEgY29udGludW91cyBvdXRjb21lICRZJCwgYSBmZXcgb2YgdGhlIG1vc3RseSBjb21tb25seSB1c2VkIGRpc3RhbmNlIG1ldHJpY3MgYXJlOiAKCjEuIG1lYW4gYWJzb2x1dGUgZXJyb3IgKGBtYWVgKSAgCgokJE1BRSA9IFxmcmFje1xzdW1fe2k9MX1ee259eyh8XGhhdHt5X3R9LSB5X3R8KX1eMn17bn0kJAoKCjIuIFIgc3F1YXJlZCBlcnJvciAoYHJzcWApIC0tIHRoaXMgaXMgYWxzbyBrbm93biBhcyB0aGUgY29lZmZpY2llbnQgb2YgZGV0ZXJtaW5hdGlvbiB3aGljaCBpcyB0aGUgc3F1YXJlZCBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRydXRoIGFuZCBlc3RpbWF0ZQoKVGhpcyBpcyBjYWxjdWxhdGVkIGFuZCAxIG1pbnVzIHRoZSBmcmFjdGlvbiBvZiB0aGUgcmVzaWR1YWwgc3VtIG9mIHNxdWFyZXMgKCRTU19yZXMkKSBieSB0aGUgdG90YWwgc3VtIG9mIHNxdWFyZXMgKCRTU190b3QkKQoKCiQkUlNRID0gUl4yID0gMSAtIFxmcmFje1NTcmVzfXtTU3RvdH0kJAoKJCRTU197dG90fSA9IFxzdW1fe2k9MX1ee259eyh5X2ktIFxiYXJ7eX0pfV4yJCQKVGhlIHRvdGFsIHN1bSBvZiBzcXVhcmVzIGlzIHByb3BvcnRpb25hbCB0byB0aGUgdmFyaWFuY2Ugb2YgdGhlIGRhdGEuIEl0IGlzIGNhbGN1bGF0ZWQgYXMgdGhlIHN1bSBvZiBlYWNoICB0cnVlIHZhbHVlIGZyb20gdGhlIG1lYW4gdHJ1ZSB2YWx1ZSAoJFxiYXJ7eX0kKS4KCiQkU1Nfe3Jlc30gPSBcc3VtX3tpPTF9XntufXsoeV9pLSBcaGF0e3lfaX0pfV4yJCQKClRoZSBzdW0gb2Ygc3F1YXJlcyBvZiByZXNpZHVhbHMgaXMgY2FsY3VsYXRlZCBhcyB0aGUgc3VtIG9mIGVhY2ggcHJlZGljdGVkIHZhbHVlICgkXGhhdHt5X2l9JCBvciBzb21ldGltZXMgJGZfaSQpIGZyb20gdGhlIHRydWUgdmFsdWUgKCR5X2kkKS4gCgoKMy4gW3Jvb3QgbWVhbiBzcXVhcmVkIGVycm9yXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Sb290LW1lYW4tc3F1YXJlX2RldmlhdGlvbil7dGFyZ2V0PSJfYmxhbmsifSAoYHJtc2VgKSAgIAoKJCRSTVNFID0gXHNxcnR7XGZyYWN7XHN1bV97aT0xfV57bn17KFxoYXR7eV90fS0geV90KX1eMn17bn19JCQKCgoKCk9uZSB3YXkgdG8gY2FsY3VsYXRlIHRoZXNlIG1ldHJpY3Mgd2l0aGluIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrIGlzIHRvIHVzZSB0aGUgYHlhcmRzdGlja2AgcGFja2FnZSB1c2luZyB0aGUgYG1ldHJpY3MoKWAgZnVuY3Rpb24uIAoKYGBge3J9CnlhcmRzdGljazo6bWV0cmljcyh3Zl9maXR0ZWRfdmFsdWVzLCAKICAgICAgICAgICAgICAgICAgIHRydXRoID0gdmFsdWUsIGVzdGltYXRlID0gLmZpdHRlZCkKYGBgCgpBbHRlcm5hdGl2ZWx5IGlmIHlvdSBvbmx5IHdhbnRlZCBvbmUgbWV0cmljIHlvdSBjb3VsZCB1c2UgdGhlIGBtYWUoKWAsIGByc3EoKWAsIG9yIGBybXNlKClgIGZ1bmN0aW9ucywgcmVzcGVjdGl2ZWx5LiAKCmBgYHtyfQp5YXJkc3RpY2s6Om1hZSh3Zl9maXR0ZWRfdmFsdWVzLCAKICAgICAgICAgICAgICAgdHJ1dGggPSB2YWx1ZSwgZXN0aW1hdGUgPSAuZml0dGVkKQpgYGAKCiMjIENyb3NzIHZhbGlkYXRpb24KClVudGlsIG5vdyB3ZSBoYXZlIHVzZWQgZXZlcnl0aGluZyBpbiBvdXIgInRyYWluaW5nIiBkYXRhc2V0IChhbmQgaGF2ZSBub3QgdG91Y2hlZCB0aGUgInRlc3RpbmciIGRhdGFzZXQpIGZyb20gdGhlIGByc2FtcGxlYCBwYWNrYWdlIHRvIGJ1aWxkIG91ciBtYWNoaW5lIGxlYXJuaW5nIChNTCkgbW9kZWwgJFxoYXR7WX0gPSBmKFgpJCAob3IgdG8gZXN0aW1hdGUgJGYkIHVzaW5nIHRoZSBmZWF0dXJlcyBvciBwcmVkaWN0b3IgdmFyaWFibGUgJFgkKS4gCgpIZXJlLCB3ZSB0YWtlIG1vdmUgdGhpcyBiZXlvbmQgdGhlIHNpbXBsZSBzcGxpdCBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEgc2V0cy4gCldlIHdpbGwgYWdhaW4gdXNlIHRoZSBgcnNhbXBsZWAgcGFja2FnZSBhZ2FpbiBpbiBvcmRlciB0byBmdXJ0aGVyIGltcGxlbWVudCB3aGF0IGFyZSBjYWxsZWQgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IHRlY2huaXF1ZXMuIFRoaXMgaXMgYWxzbyBjYWxsZWQgKipyZS1zYW1wbGluZyoqIG9yICoqcmVwYXJ0aW9uaW5nKiouICAKCioqTm90ZSoqOiB3ZSBhcmUgbm90IGFjdHVhbGx5IGdldHRpbmcgbmV3IHNhbXBsZXMgZnJvbSB0aGUgdW5kZXJseWluZyBkaXN0cmlidXRpb24gc28gdGhlIHRlcm0gcmUtc2FtcGxpbmcgaXMgYSBiaXQgb2YgYSBtaXNub21lci4KCltDcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSBzcGxpdHMgb3VyIHRyYWluaW5nIGRhdGEgaW50byBtdWx0aXBsZSB0cmFpbmluZyBkYXRhIHNldHMgdG8gYWxsb3cgZm9yIGEgZGVlcGVyIGFzc2Vzc21lbnQgb2YgdGhlIGFjY3VyYWN5IG9mIHRoZSBtb2RlbC4KCkhlcmUgaXMgYSB2aXN1YWxpemF0aW9uIG9mIHRoZSBjb25jZXB0IGZvciBjcm9zcyB2YWxpZGF0aW9uL3Jlc2FtcGxpbmcvcmVwYXJ0aXRpb25pbmcgZnJvbSBbTWF4IEt1aG5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvbWF4LWt1aG4pe3RhcmdldD0iX2JsYW5rIn06CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInJlc2FtcGxpbmcucG5nIikpCmBgYAoKVGVjaG5pY2FsbHkgY3JlYXRpbmcgb3VyIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldCBvdXQgb2Ygb3VyIG9yaWdpbmFsIHRyYWluaW5nIGRhdGEgaXMgc29tZXRpbWVzIGNvbnNpZGVyZWQgYSBmb3JtIG9mIFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSwgY2FsbGVkIHRoZSBob2xkb3V0IG1ldGhvZC4gClRoZSByZWFzb24gd2UgZG8gdGhpcyBpdCBzbyB3ZSBjYW4gZ2V0IGEgYmV0dGVyIHNlbnNlIG9mIHRoZSBhY2N1cmFjeSBvZiBvdXIgbW9kZWwgdXNpbmcgZGF0YSB0aGF0IHdlIGRpZCBub3QgdHJhaW4gaXQgb24uIAoKSG93ZXZlciwgd2UgY2FuIGFjdHVhbGx5IGRvIGEgYmV0dGVyIGpvYiBvZiBvcHRpbWl6aW5nIG91ciBtb2RlbCBmb3IgYWNjdXJhY3kgaWYgd2UgYWxzbyBwZXJmb3JtIGFub3RoZXIgdHlwZSBvZiBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gb24gdGhlIG5ld2x5IGRlZmluZWQgdHJhaW5pbmcgc2V0IHRoYXQgd2UganVzdCBjcmVhdGVkLiAKVGhlcmUgYXJlIG1hbnkgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IG1ldGhvZHMgYW5kIG1vc3QgY2FuIGJlIGVhc2lseSBpbXBsZW1lbnRlZCB1c2luZyBgcnNhbXBsZWAgcGFja2FnZS4gCkhlcmUsIHdlIHdpbGwgdXNlIGEgdmVyeSBwb3B1bGFyIG1ldGhvZCBjYWxsZWQgZWl0aGVyIFtrLWZvbGQgb3Igdi1mb2xkIGNyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vay1mb2xkLWNyb3NzLXZhbGlkYXRpb24vKXt0YXJnZXQ9Il9ibGFuayJ9LiAKClRoaXMgbWV0aG9kIGludm9sdmVzIGVzc2VudGlhbGx5IHByZWZvcm1pbmcgdGhlIGhvbGQgb3V0IG1ldGhvZCBpdGVyYXRpdmVseSB3aXRoIHRoZSB0cmFpbmluZyBkYXRhLiAKCkZpcnN0LCB0aGUgdHJhaW5pbmcgc2V0IGlzIGRpdmlkZWQgaW50byAkdiQgKG9yIG9mdGVuIGNhbGxlZCBjYWxsZWQgJGskKSBlcXVhbGx5IHNpemVkIHNtYWxsZXIgcGllY2VzLiAKCk5leHQsIHRoZSBtb2RlbCBpcyB0cmFpbmVkIG9uIHRoZSBtb2RlbCBvbiAkdiQtMSBzdWJzZXRzIG9mIHRoZSBkYXRhIGl0ZXJhdGl2ZWx5IChyZW1vdmluZyBhIGRpZmZlcmVudCAkdiQgdW50aWwgYWxsIHBvc3NpYmxlICR2JC0xIHNldHMgaGF2ZSBiZWVuIGV2YWx1YXRlZCkgdG8gZ2V0IGEgc2Vuc2Ugb2YgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBtb2RlbC4gClRoaXMgaXMgcmVhbGx5IHVzZWZ1bCBmb3IgZmluZSB0dW5pbmcgc3BlY2lmaWMgYXNwZWN0cyBvZiB0aGUgbW9kZWwgaW4gYSBwcm9jZXNzIGNhbGxlZCBtb2RlbCB0dW5pbmcsIHdoaWNoIHdlIHdpbGwgbGVhcm4gYWJvdXQgaW4gdGhlIG5leHQgc2VjdGlvbi4gCgpIZXJlIGlzIGEgdmlzdWFsaXphdGlvbiBvZiBob3cgdGhlIGZvbGRzIGFyZSBjcmVhdGVkOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidmZvbGQucG5nIikpCmBgYAoKKipOb3RlKio6IFBlb3BsZSB0eXBpY2FsbHkgaWdub3JlIHNwYXRpYWwgZGVwZW5kZW5jZSB3aXRoIGNyb3NzIHZhbGlkYXRpb24gb2YgYWlyIHBvbGx1dGlvbiBtb25pdG9yaW5nIGRhdGEgaW4gdGhlIGFpciBwb2xsdXRpb24gZmllbGQsIHNvIHdlIHdpbGwgZG8gdGhlIHNhbWUuICBIb3dldmVyLCBpdCBtaWdodCBtYWtlIHNlbnNlIHRvIGxlYXZlIG91dCBibG9ja3Mgb2YgbW9uaXRvcnMgcmF0aGVyIHRoYW4gIHJhbmRvbSBpbmRpdmlkdWFsIG1vbml0b3JzIHRvIGhlbHAgYWNjb3VudCBmb3Igc29tZSBzcGF0aWFsIGRlcGVuZGVuY2UuCgojIyMgQ3JlYXRpbmcgdGhlICR2JC1mb2xkcyB1c2luZyBgcnNhbXBsZWAKClRoZSBbYHZmb2xkX2N2KClgXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JzYW1wbGUvcmVmZXJlbmNlL3Zmb2xkX2N2Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gZnVuY3Rpb24gb2YgdGhlIGByc2FtcGxlYCBwYWNrYWdlIGNhbiBiZSB1c2VkIHRvIHBhcnNlIHRoZSB0cmFpbmluZyBkYXRhIGludG8gZm9sZHMgZm9yICR2JC1mb2xkIGNyb3NzIHZhbGlkYXRpb24uCgotIFRoZSBgdmAgYXJndW1lbnQgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgZm9sZHMgdG8gY3JlYXRlLgotIFRoZSBgcmVwZWF0c2AgYXJndW1lbnQgc3BlY2lmaWVzIGlmIGFueSBzYW1wbGVzIHNob3VsZCBiZSByZXBlYXRlZCBhY3Jvc3MgZm9sZHMgLSBkZWZhdWx0IGlzIGBGQUxTRWAKLSBUaGUgYHN0cmF0YWAgYXJndW1lbnQgc3BlY2lmaWVzIGEgdmFyaWFibGUgdG8gc3RyYXRpZnkgc2FtcGxlcyBhY3Jvc3MgZm9sZHMgLSBqdXN0IGxpa2UgaW4gYGluaXRpYWxfc3BsaXQoKWAuCgpBZ2FpbiwgYmVjYXVzZSB0aGVzZSBhcmUgY3JlYXRlZCBhdCByYW5kb20sIHdlIG5lZWQgdG8gdXNlIHRoZSBiYXNlIGBzZXQuc2VlZCgpYCBmdW5jdGlvbiBpbiBvcmRlciB0byBvYnRhaW4gdGhlIHNhbWUgcmVzdWx0cyBlYWNoIHRpbWUgd2Uga25pdCB0aGlzIGRvY3VtZW50LiAKR2VuZXJhbGx5IHNwZWFraW5nIHVzaW5nIDEwIGZvbGRzIGlzIGdvb2QgcHJhY3RpY2UsIGJ1dCB0aGlzIGRlcGVuZHMgb24gdGhlIHZhcmlhYmlsaXR5IHdpdGhpbiB5b3VyIGRhdGEuIApXZSBhcmUgZ29pbmcgdG8gdXNlIDQgZm9yIHRoZSBzYWtlIG9mIGV4cGVkaWVuY3kuIAoKYGBge3J9CnNldC5zZWVkKDEyMzQpCnZmb2xkX3BtIDwtIHJzYW1wbGU6OnZmb2xkX2N2KGRhdGEgPSB0cmFpbl9wbSwgdiA9IDQpCnZmb2xkX3BtCnB1bGwodmZvbGRfcG0sIHNwbGl0cykKYGBgCgpOb3cgd2UgY2FuIHNlZSB0aGF0IHdlIGhhdmUgY3JlYXRlZCA0IGZvbGRzIG9mIHRoZSBkYXRhIGFuZCB3ZSBjYW4gc2VlIGhvdyBtYW55IHZhbHVlcyB3ZXJlIHNldCBhc2lkZSBmb3IgdGVzdGluZyAoY2FsbGVkIGFzc2Vzc2luZyBmb3IgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzKSBhbmQgdHJhaW5pbmcgKGNhbGxlZCBhbmFseXNpcyBmb3IgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzKSB3aXRoaW4gZWFjaCBmb2xkLgoKT25jZSB0aGUgZm9sZHMgYXJlIGNyZWF0ZWQgdGhleSBjYW4gYmUgdXNlZCB0byBldmFsdWF0ZSBwZXJmb3JtYW5jZSBieSBmaXR0aW5nIHRoZSBtb2RlbCB0byBlYWNoIG9mIHRoZSByZS1zYW1wbGVzIHRoYXQgd2UgY3JlYXRlZDoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImNyb3NzX3ZhbGlkYXRpb24ucG5nIikpCmBgYAoKIyMjIEFzc2Vzc2luZyBtb2RlbCBwZXJmb3JtYW5jZSBvbiAkdiQtZm9sZHMgdXNpbmcgYHR1bmVgCgpXZSBjYW4gZml0IHRoZSBtb2RlbCB0byBvdXIgY3Jvc3MgdmFsaWRhdGlvbiBmb2xkcyB1c2luZyB0aGUgYGZpdF9yZXNhbXBsZXMoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlLCBieSBzcGVjaWZ5aW5nIG91ciBgd29ya2Zsb3dgIG9iamVjdCBhbmQgdGhlIGNyb3NzIHZhbGlkYXRpb24gZm9sZCBvYmplY3Qgd2UganVzdCBjcmVhdGVkLiAKU2VlIFtoZXJlXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3R1bmUvcmVmZXJlbmNlL2ZpdF9yZXNhbXBsZXMuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBpbmZvcm1hdGlvbi4KCgpgYGB7cn0KcmVzYW1wbGVfZml0IDwtIHR1bmU6OmZpdF9yZXNhbXBsZXMoUE1fd2Zsb3csIHZmb2xkX3BtKQpgYGAKCldlIGNhbiBub3cgdGFrZSBhIGxvb2sgYXQgdmFyaW91cyBwZXJmb3JtYW5jZSBtZXRyaWNzIGJhc2VkIG9uIHRoZSBmaXQgb2Ygb3VyIGNyb3NzIHZhbGlkYXRpb24gInJlc2FtcGxlcyIuIApUbyBkbyB0aGlzIHdlIHdpbGwgdXNlIHRoZSBgc2hvd19iZXN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZS4KCmBgYHtyfQp0dW5lOjpzaG93X2Jlc3QocmVzYW1wbGVfZml0LCBtZXRyaWMgPSAicm1zZSIpCmBgYAoKSGVyZSB3ZSBjYW4gc2VlIHRoZSBtZWFuIGBSTVNFYCB2YWx1ZSBhY3Jvc3MgYWxsIGZvdXIgZm9sZHMuIFRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgYHNob3dfYmVzdCgpYCBiZWNhdXNlIGl0IGlzIGFsc28gdXNlZCBmb3IgbW9kZWwgdHVuaW5nIGFuZCBpdCB3aWxsIHNob3cgdGhlIHBhcmFtZXRlciBjb21iaW5hdGlvbiB3aXRoIHRoZSBiZXN0IHBlcmZvcm1hbmNlLCB3ZSB3aWxsIGRpc2N1c3MgdGhpcyBtb3JlIGxhdGVyIGluIHRoZSBjYXNlIHN0dWR5LgoKCiMgKipEYXRhIEFuYWx5c2lzKioKKioqCgpJbiB0aGUgcHJldmlvdXMgc2VjdGlvbiwgd2UgZGVtb25zdHJhdGVkIGhvdyB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwgKHNwZWNpZmljYWxseSBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsKSB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gd2l0aCB0aGUgYHRpZHltb2RlbHNgIGZyYW1ld29yay4gCgpJbiB0aGUgbmV4dCBmZXcgc2VjdGlvbiwgd2Ugd2lsbCBkZW1vbnN0cmF0ZSBhbm90aGVyIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwuIAoKCiMjIFJhbmRvbSBGb3Jlc3QKCk5vdywgd2UgYXJlIGdvaW5nIHRvIHByZWRpY3Qgb3VyIG91dGNvbWUgdmFyaWFibGUgKGFpciBwb2xsdXRpb24pIHVzaW5nIGEgZGVjaXNpb24gdHJlZSBtZXRob2QgY2FsbGVkIFtyYW5kb20gZm9yZXN0XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SYW5kb21fZm9yZXN0KXt0YXJnZXQ9Il9ibGFuayJ9LgoKQSBbZGVjaXNpb24gdHJlZV0oaHR0cHM6Ly9tZWRpdW0uY29tL2dyZXlhdG9tL2RlY2lzaW9uLXRyZWVzLWEtc2ltcGxlLXdheS10by12aXN1YWxpemUtYS1kZWNpc2lvbi1kYzUwNmE0MDNhZWIpe3RhcmdldD0iX2JsYW5rIn0gaXMgYSB0b29sIHRvIHBhcnRpdGlvbiBkYXRhIG9yIGFueXRoaW5nIHJlYWxseSwgYmFzZWQgb24gYSBzZXJpZXMgb2Ygc2VxdWVudGlhbCAob2Z0ZW4gYmluYXJ5KSBkZWNpc2lvbnMsIHdoZXJlIHRoZSBkZWNpc2lvbnMgYXJlIGNob3NlbiBiYXNlZCBvbiB0aGVpciBhYmlsaXR5IHRvIG9wdGltYWxseSBzcGxpdCB0aGUgZGF0YS4KCkhlcmUgeW91IGNhbiBzZWUgYSBzaW1wbGUgZXhhbXBsZToKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTAwMC8xKkxNb0ptWENzUWxjaUdURXlvU04zOWcuanBlZyIpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdW5kZXJzdGFuZGluZy1yYW5kb20tZm9yZXN0LTU4MzgxZTA2MDJkMil7dGFyZ2V0PSJfYmxhbmsifQoKSW4gdGhlIGNhc2Ugb2YgW3JhbmRvbSBmb3Jlc3RdKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9kZWNpc2lvbi10cmVlLWVuc2VtYmxlcy1iYWdnaW5nLWFuZC1ib29zdGluZy0yNjZhOGJhNjBmZDkpe3RhcmdldD0iX2JsYW5rIn0sIG11bHRpcGxlIGRlY2lzaW9uIHRyZWVzIGFyZSBjcmVhdGVkIC0gaGVuY2UgdGhlIG5hbWUgZm9yZXN0LCBhbmQgZWFjaCB0cmVlIGlzIGJ1aWx0IHVzaW5nIGEgcmFuZG9tIHN1YnNldCBvZiB0aGUgdHJhaW5pbmcgZGF0YSAod2l0aCByZXBsYWNlbWVudCkgLSBoZW5jZSB0aGUgZnVsbCBuYW1lIHJhbmRvbSBmb3Jlc3QuIFRoaXMgcmFuZG9tIGFzcGVjdCBoZWxwcyB0byBrZWVwIHRoZSBhbGdvcml0aG0gZnJvbSBvdmVyZml0dGluZyB0aGUgZGF0YS4KClRoZSBtZWFuIG9mIHRoZSBwcmVkaWN0aW9ucyBmcm9tIGVhY2ggb2YgdGhlIHRyZWVzIGlzIHVzZWQgaW4gdGhlIGZpbmFsIG91dHB1dC4KCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTQwMC8wKmZfcVFQRnBkb2ZXR0xRcWMucG5nIikKYGBgCgoKSW4gb3VyIGNhc2UsIHdlIGFyZSBnb2luZyB0byB1c2UgdGhlIHJhbmRvbSBmb3Jlc3QgbWV0aG9kIG9mIHRoZSB0aGUgYHJhbmRvbUZvcmVzdGAgcGFja2FnZS4gCgpUaGlzIHBhY2thZ2UgaXMgY3VycmVudGx5IG5vdCBjb21wYXRpYmxlIHdpdGggY2F0ZWdvcmljYWwgdmFyaWFibGVzIHRoYXQgaGF2ZSBtb3JlIHRoYW4gNTMgbGV2ZWxzLiBTZWUgW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5kb21Gb3Jlc3QvTkVXUykgZm9yIHRoZSBkb2N1bWVudGF0aW9uIGFib3V0IHdoZW4gdGhpcyB3YXMgdXBkYXRlZCBmcm9tIDI1IGxldmVscy4gVGh1cyB3ZSB3aWxsIHJlbW92ZSB0aGUgYHpjdGFgICBhbmQgYGNvdW50eWAgdmFyaWFibGVzLgoKTm90ZSB0aGF0IHRoZSBgc3RlcF9ub3ZlbCgpYCBmdW5jdGlvbiBpcyBuZWNlc3NhcnkgaGVyZSBmb3IgdGhlIGBzdGF0ZWAgdmFyaWFibGUgdG8gZ2V0IGFsbCBjcm9zcyB2YWxpZGF0aW9uIGZvbGRzIHRvIHdvcmssIGJlY2F1c2UgdGhlcmUgd2lsbCBiZSBkaWZmZXJlbnQgbGV2ZWxzIGluY2x1ZGVkIGluIGVhY2ggZm9sZCB0ZXN0IGFuZCB0cmFpbmluZyBzZXRzLiBUaGUgbmV3IGxldmVscyBmb3Igc29tZSBvZiB0aGUgdGVzdCBzZXRzIHdvdWxkIG90aGVyd2lzZSByZXN1bHQgaW4gYW4gZXJyb3IuCgpBY2NvcmRpbmcgdG8gdGhlIFtkb2N1bWVudGF0aW9uXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvcmVjaXBlcy92ZXJzaW9ucy8wLjEuMTMvdG9waWNzL3N0ZXBfbm92ZWwpIGZvciB0aGUgYHJlY2lwZXNgIHBhY2thZ2U6Cgo+IHN0ZXBfbm92ZWwgY3JlYXRlcyBhIHNwZWNpZmljYXRpb24gb2YgYSByZWNpcGUgc3RlcCB0aGF0IHdpbGwgYXNzaWduIGEgcHJldmlvdXNseSB1bnNlZW4gZmFjdG9yIGxldmVsIHRvIGEgbmV3IHZhbHVlLgoKYGBge3J9ClJGX3JlYyA8LSByZWNpcGUodHJhaW5fcG0pICU+JQogICAgdXBkYXRlX3JvbGUoZXZlcnl0aGluZygpLCBuZXdfcm9sZSA9ICJwcmVkaWN0b3IiKSU+JQogICAgdXBkYXRlX3JvbGUodmFsdWUsIG5ld19yb2xlID0gIm91dGNvbWUiKSU+JQogICAgdXBkYXRlX3JvbGUoaWQsIG5ld19yb2xlID0gImlkIHZhcmlhYmxlIikgJT4lCiAgICB1cGRhdGVfcm9sZSgiZmlwcyIsIG5ld19yb2xlID0gImNvdW50eSBpZCIpICU+JQogICAgc3RlcF9ub3ZlbCgic3RhdGUiKSAlPiUKICAgIHN0ZXBfc3RyaW5nMmZhY3Rvcigic3RhdGUiLCAiY291bnR5IiwgImNpdHkiKSAlPiUKICAgIHN0ZXBfcm0oImNvdW50eSIpICU+JQogICAgc3RlcF9ybSgiemN0YSIpICU+JQogICAgc3RlcF9jb3JyKGFsbF9udW1lcmljKCkpJT4lCiAgICBzdGVwX256dihhbGxfbnVtZXJpYygpKQpgYGAKClRoZSBgcmFuZF9mb3Jlc3QoKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlIGhhcyB0aHJlZSBpbXBvcnRhbnQgYXJndW1lbnRzIHRoYXQgYWN0IGFzIGFuIGludGVyZmFjZSBmb3IgdGhlIGRpZmZlcmVudCBwb3NzaWJsZSBlbmdpbmVzIHRvIHBlcmZvcm0gYSByYW5kb20gZm9yZXN0IGFuYWx5c2lzOgoKMS4gYG10cnlgIC0gVGhlIG51bWJlciBvZiBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscy4gVGhlIGRlZmF1bHQgbnVtYmVyIGZvciByZWdyZXNzaW9uIGFuYWx5c2VzIGlzIHRoZSBudW1iZXIgb2YgcHJlZGljdG9ycyBkaXZpZGVkIGJ5IDMuIAoyLiBgbWluX25gIC0gVGhlIG1pbmltdW0gbnVtYmVyIG9mIGRhdGEgcG9pbnRzIGluIGEgbm9kZSB0aGF0IGFyZSByZXF1aXJlZCBmb3IgdGhlIG5vZGUgdG8gYmUgc3BsaXQgZnVydGhlci4KMy4gYHRyZWVzYCAtIHRoZSBudW1iZXIgb2YgdHJlZXMgaW4gdGhlIGVuc2VtYmxlCgpXZSB3aWxsIHN0YXJ0IGJ5IHRyeWluZyBhbiBgbXRyeWAgdmFsdWUgb2YgMTAgYW5kIGEgYG1pbl9uYCB2YWx1ZSBvZiAzLgoKTm93IHRoYXQgd2UgaGF2ZSBvdXIgcmVjaXBlIChgUkZfcmVjYCksIGxldCdzIHNwZWNpZnkgdGhlIG1vZGVsIHdpdGggYHJhbmRfZm9yZXN0KClgIGZyb20gYHBhcnNuaXBgIHdpdGggdGhlIGBtb2RlID0gInJlZ3Jlc3Npb24iYCBhcmd1bWVudCB0byBzcGVjaWZ5IG91ciBvdXRjb21lIHZhcmlhYmxlIChhaXIgcG9sbHV0aW9uKSBpcyBjb250aW51b3VzLiAKCmBgYHtyfQpQTXRyZWVfbW9kZWwgPC0gCiAgcGFyc25pcDo6cmFuZF9mb3Jlc3QobXRyeSA9IDEwLCBtaW5fbiA9IDMsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZGUgPSAicmVncmVzc2lvbiIpClBNdHJlZV9tb2RlbApgYGAKCk5leHQsIHdlIHNldCB0aGUgZW5naW5lIGFuZCBtb2RlOgoKTm90ZSB0aGF0IHlvdSBjb3VsZCBhbHNvIHVzZSB0aGUgYHJhbmdlcmAgb3IgYHNwYXJrYCBwYWNrYWdlcyBpbnN0ZWFkIG9mIGByYW5kb21Gb3Jlc3RgLgpJZiB5b3Ugd2VyZSB0byB1c2UgdGhlIGByYW5nZXJgIHBhY2thZ2UgdG8gaW1wbGVtZW50IHRoZSByYW5kb20gZm9yZXN0IGFuYWx5c2lzIHlvdSB3b3VsZCBuZWVkIHRvIHNwZWNpZnkgYW4gYGltcG9ydGFuY2VgIGFyZ3VtZW50IHRvIGJlIGFibGUgdG8gZXZhbHVhdGUgcHJlZGljdG9yIGltcG9ydGFuY2UuICBUaGUgb3B0aW9ucyBhcmUgYGltcHVyaXR5YCBvciBgcGVybXV0YXRpb25gLgoKVGhlc2Ugb3RoZXIgcGFja2FnZXMgaGF2ZSBkaWZmZXJlbnQgYWR2YW50YWdlcyBhbmQgZGlzYWR2YW50YWdlcy0gZm9yIGV4YW1wbGUgYHJhbmdlcmAgYW5kIGBzcGFya2AgYXJlIG5vdCBhcyBsaW1pdGluZyBmb3IgdGhlIG51bWJlciBvZiBjYXRlZ29yaWVzIGZvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuIEZvciBtb3JlIGluZm9ybWF0aW9uIHNlZSB0aGVpciBkb2N1bWVudGF0aW9uOiBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3Jhbmdlci9yYW5nZXIucGRmKSBmb3IgcmFuZ2VyLCBbaGVyZV0oaHR0cDovL3NwYXJrLmFwYWNoZS5vcmcvZG9jcy9sYXRlc3QvbWxsaWItZW5zZW1ibGVzLmh0bWwjcmFuZG9tLWZvcmVzdHMpIGZvciBgc3BhcmtgLCBhbmQgW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5kb21Gb3Jlc3QvcmFuZG9tRm9yZXN0LnBkZikgZm9yIGByYW5kb21Gb3Jlc3RgLgoKU2VlIFtoZXJlXShodHRwczovL3BhcnNuaXAudGlkeW1vZGVscy5vcmcvcmVmZXJlbmNlL3JhbmRfZm9yZXN0Lmh0bWwpIGZvciBtb3JlIGRvY3VtZW50YXRpb24gYWJvdXQgaW1wbGVtZW50aW5nIHRoZXNlIGVuZ2luZSBvcHRpb25zIHdpdGggdGlkeW1vZGVscy4gTm90ZSB0aGF0IHRoZXJlIGFyZSBhbHNvIFtvdGhlcl0oaHR0cHM6Ly93d3cubGlua2VkaW4uY29tL3B1bHNlL2RpZmZlcmVudC1yYW5kb20tZm9yZXN0LXBhY2thZ2VzLXItbWFkaHVyLW1vZGkvKSBSIHBhY2thZ2VzIGZvciBpbXBsZW1lbnRpbmcgcmFuZG9tIGZvcmVzdCBhbGdvcml0aG1zLCBidXQgdGhlc2UgdGhyZWUgcGFja2FnZXMgKGByYW5nZXJgLCBgc3BhcmtgLCBhbmQgYHJhbmRvbUZvcmVzdGApIGFyZSBjdXJyZW50bHkgY29tcGF0aWJsZSB3aXRoIGB0aWR5bW9kZWxzYC4KCmBgYHtyfQoKUkZfUE1fbW9kZWwgPC0gCiAgUE10cmVlX21vZGVsICU+JQogIHNldF9lbmdpbmUoInJhbmRvbUZvcmVzdCIpICU+JQogIHNldF9tb2RlKCJyZWdyZXNzaW9uIikKClJGX1BNX21vZGVsCmBgYAoKVGhlbiwgd2UgcHV0IHRoaXMgYWxsIHRvZ2V0aGVyIGludG8gYSBgd29ya2Zsb3dgOiAKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpTZWUgaWYgeW91IGNhbiBjb21lIHVwIHdpdGggdGhlIGNvZGUgdG8gZG8gdGhpcy4KCiMjIyMKCioqKgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4KCmBgYHtyfQpSRl93ZmxvdyA8LSB3b3JrZmxvd3M6OndvcmtmbG93KCkgJT4lCiAgICAgICAgICAgIHdvcmtmbG93czo6YWRkX3JlY2lwZShSRl9yZWMpICU+JQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9tb2RlbChSRl9QTV9tb2RlbCkKCmBgYAo8L2RldGFpbHM+IAoqKioKCmBgYHtyfQpSRl93ZmxvdwpgYGAKCgpGaW5hbGx5LCB3ZSBmaXQgdGhlIGRhdGEgdG8gdGhlIG1vZGVsOgoKIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4KCkRvIHlvdSByZWNhbGwgaG93IHRvIGRvIHRoaXM/CgojIyMjCgoqKioKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CgpgYGB7cn0KUkZfd2Zsb3dfZml0IDwtIHBhcnNuaXA6OmZpdChSRl93ZmxvdywgZGF0YSA9IHRyYWluX3BtKQpgYGAKPC9kZXRhaWxzPiAKKioqCgpgYGB7cn0KUkZfd2Zsb3dfZml0CmBgYAoKTGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIHRvcCAxMCBjb250cmlidXRpbmcgdmFyaWFibGVzOgoKIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4KClNlZSBpZiB5b3UgY2FuIHJlY2FsbCBob3cgdG8gZG8gdGhpcy4KCiMjIyMKCmBgYHtyLCBlY2hvID0gRkFMU0V9ClJGX3dmbG93X2ZpdCAlPiUgCiAgcHVsbF93b3JrZmxvd19maXQoKSAlPiUgCiAgdmlwKG51bV9mZWF0dXJlcyA9IDEwKQoKYGBgCgoKKioqCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5PgoKYGBge3J9ClJGX3dmbG93X2ZpdCAlPiUgCiAgcHVsbF93b3JrZmxvd19maXQoKSAlPiUgCiAgdmlwKG51bV9mZWF0dXJlcyA9IDEwKQpgYGAKPC9kZXRhaWxzPgoqKioKCgpJbnRlcmVzdGluZyEgSW4gdGhlIHByZXZpb3VzIG1vZGVsIHRoZSBDTUFRIHZhbHVlcyBhbmQgdGhlIHN0YXRlIHdoZXJlIHRoZSBtb25pdG9yIHdhcyBsb2NhdGVkIHdlcmUgYWxzbyB0aGUgdG9wIHR3byBtb3N0IGltcG9ydGFudCwgaG93ZXZlciBwcmVkaWN0b3JzIGFib3V0IGVkdWNhdGlvbiBsZXZlbHMgb2YgdGhlIGNvbW11bml0aWVzIHdoZXJlIHRoZSBtb25pdG9yIHdhcyBsb2NhdGVkIHdhcyBhbW9uZyB0aGUgdG9wIG1vc3QgaW1wb3J0YW50LiBOb3cgd2Ugc2VlIHRoYXQgcG9wdWxhdGlvbiBkZW5zaXR5IGFuZCBwcm94aW1pdHkgdG8gc291cmNlcyBvZiBlbWlzc2lvbnMgYW5kIHJvYWRzIGFyZSBhbW9uZyB0aGUgdG9wIHRlbi4KCgpOb3cgbGV0J3MgdGFrZSBhIGxvb2sgYXQgbW9kZWwgcGVyZm9ybWFuY2UgYnkgZml0dGluZyB0aGUgZGF0YSB1c2luZyBjcm9zcyB2YWxpZGF0aW9uOgoKIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4KClNlZSBpZiB5b3UgY2FuIHJlY2FsbCBob3cgdG8gZG8gdGhpcy4KCiMjIyMKCioqKgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4KCmBgYHtyLCBldmFsID0gRkFMU0V9CnNldC5zZWVkKDQ1NikKcmVzYW1wbGVfUkZfZml0IDwtIHR1bmU6OmZpdF9yZXNhbXBsZXMoUkZfd2Zsb3csIHZmb2xkX3BtKQpjb2xsZWN0X21ldHJpY3MocmVzYW1wbGVfUkZfZml0KQpgYGAKCjwvZGV0YWlscz4KKioqCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpzZXQuc2VlZCg0NTYpCnJlc2FtcGxlX1JGX2ZpdCA8LSB0dW5lOjpmaXRfcmVzYW1wbGVzKFJGX3dmbG93LCB2Zm9sZF9wbSkKY29sbGVjdF9tZXRyaWNzKHJlc2FtcGxlX1JGX2ZpdCkKYGBgCgpOb3cgbGV0J3MgY29tcGFyZSB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhpcyBtb2RlbCB3aXRoIG91ciBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbDoKCmBgYHtyfQojIG91ciBpbml0aWFsIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsOgpjb2xsZWN0X21ldHJpY3MocmVzYW1wbGVfZml0KQpgYGAKCk9LLCBzbyBvdXIgZmlyc3QgbW9kZWwgaGFkIGEgbWVhbiBgcm1zZWAgdmFsdWUgb2YgMi4xNy4KSXQgbG9va3MgbGlrZSB0aGUgcmFuZG9tIGZvcmVzdCBtb2RlbCBoYWQgIGEgbXVjaCBsb3dlciBgcm1zZWAgdmFsdWUgb2YgMS43Mi4KCiMjIyMgey50aGlua19xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpEbyB5b3UgcmVjYWxsIGhvdyB0aGUgUk1TRSBpcyBjYWxjdWxhdGVkPwoKIyMjIwoKKioqCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4KJCRSTVNFID0gXHNxcnR7XGZyYWN7XHN1bV97aT0xfV57bn17KFxoYXR7eV90fS0geV90KX1eMn17bn19JCQKPC9kZXRhaWxzPiAKCklmIHdlIHR1bmVkIG91ciByYW5kb20gZm9yZXN0IG1vZGVsIGJhc2VkIG9uIHRoZSBudW1iZXIgb2YgdHJlZXMgb3IgdGhlIHZhbHVlIGZvciBgbXRyeWAgKHdoaWNoIGlzICJUaGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscyIpLCB3ZSBtaWdodCBnZXQgYSBtb2RlbCB3aXRoIGV2ZW4gYmV0dGVyIHBlcmZvcm1hbmNlLgoKSG93ZXZlciwgb3VyIGNyb3NzIHZhbGlkYXRlZCBtZWFuIHJtc2UgdmFsdWUgb2YgMS43MiBpcyBxdWl0ZSBnb29kIGJlY2F1c2Ugb3VyIHJhbmdlIG9mIHRydWUgb3V0Y29tZSB2YWx1ZXMgaXMgbXVjaCBsYXJnZXI6IChgciByb3VuZChyYW5nZSh0ZXN0X3BtJHZhbHVlKSwzKWApLgoKCiMjIE1vZGVsIHR1bmluZwoKW0h5cGVycGFyYW1ldGVyc10oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9kaWZmZXJlbmNlLWJldHdlZW4tYS1wYXJhbWV0ZXItYW5kLWEtaHlwZXJwYXJhbWV0ZXIvKSBhcmUgb2Z0ZW4gdGhpbmdzIHRoYXQgd2UgbmVlZCB0byBzcGVjaWZ5IGFib3V0IGEgbW9kZWwuIEZvciBleGFtcGxlLCB0aGUgbnVtYmVyIG9mIHByZWRpY3RvciB2YXJpYWJsZXMgKG9yIGZlYXR1cmVzKSB0aGF0IHdpbGwgYmUgcmFuZG9tbHkgc2FtcGxlZCBhdCBlYWNoIHNwbGl0IHdoZW4gY3JlYXRpbmcgdGhlIHRyZWUgbW9kZWxzIGNhbGxlZCBgbXRyeWAgaXMgYSBoeXBlcnBhcmFtZXRlci4gVGhlIGRlZmF1bHQgbnVtYmVyIGZvciByZWdyZXNzaW9uIGFuYWx5c2VzIGlzIHRoZSBudW1iZXIgb2YgcHJlZGljdG9ycyBkaXZpZGVkIGJ5IDMuIEluc3RlYWQgb2YgYXJiaXRyYXJpbHkgc3BlY2lmeWluZyB0aGlzLCB3ZSBjYW4gdHJ5IHRvIGRldGVybWluZSB0aGUgYmVzdCBvcHRpb24gZm9yIG1vZGVsIHBlcmZvcm1hbmNlIGJ5IGEgcHJvY2VzcyBjYWxsZWQgdHVuaW5nLiAKCgpOb3cgbGV0J3MgdHJ5IHNvbWUgdHVuaW5nLgoKTGV0J3MgdGFrZSBhIGNsb3NlciBsb29rIGF0IHRoZSBgbXRyeWAgYW5kIGBtaW5fbmAgaHlwZXJwYXJhbWV0cnMgaW4gb3VyIFJhbmRvbSBGb3Jlc3QgbW9kZWwuCgpXZSBhcmVuJ3QgZXhhY3RseSBzdXJlIHdoYXQgdmFsdWVzIG9mIGBtdHJ5YCBhbmQgYG1pbl9uYCBhY2hpZXZlIGdvb2QgYWNjdXJhY3kgeWV0IGtlZXAgb3VyIG1vZGVsIGdlbmVyYWxpemFibGUgZm9yIG90aGVyIGRhdGEuCgpUaGlzIGlzIHdoZW4gb3VyIGNyb3NzIHZhbGlkYXRpb24gbWV0aG9kcyBiZWNvbWUgcmVhbGx5IGhhbmR5IGJlY2F1c2Ugbm93IHdlIGNhbiB0ZXN0IG91dCBkaWZmZXJlbnQgdmFsdWVzIGZvciBlYWNoIG9mIHRoZXNlIGh5cGVycGFyYW1ldGVycyB0byBhc3Nlc3Mgd2hhdCB2YWx1ZXMgc2VlbSB0byB3b3JrIGJlc3QgZm9yIG1vZGVsIHBlcmZvcm1hbmNlIG9uIHRoZXNlIHJlc2FtcGxlcyBvZiBvdXIgdHJhaW5pbmcgc2V0IGRhdGEuCgpQcmV2aW91c2x5IHdlIHNwZWNpZmllZCBvdXIgbW9kZWwgbGlrZSBzbzoKYGBge3J9ClJGX1BNX21vZGVsIDwtIAogIHBhcnNuaXA6OnJhbmRfZm9yZXN0KG10cnkgPSAxMCwgbWluX24gPSAzLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RlID0gInJlZ3Jlc3Npb24iKSAlPiUKICBzZXRfZW5naW5lKCJyYW5kb21Gb3Jlc3QiKSAlPiUKICBzZXRfbW9kZSgicmVncmVzc2lvbiIpCgpSRl9QTV9tb2RlbApgYGAKTm93IGluc3RlYWQgb2Ygc3BlY2lmeWluZyBhIHZhbHVlIGZvciB0aGUgYG10cnlgIGFuZCBgbWluX25gIGFyZ3VtZW50cywgd2UgY2FuIHVzZSB0aGUgYHR1bmUoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIGxpa2Ugc286IGBtdHJ5ID0gdHVuZSgpYC4gVGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGVzZSBoeXBlcnBhcmFtZXRlcnMgYXJlIHRvIGJlIHR1bmVkLiAKCmBgYHtyfQoKdHVuZV9SRl9tb2RlbCA8LSByYW5kX2ZvcmVzdChtdHJ5ID0gdHVuZSgpLCBtaW5fbiA9IHR1bmUoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlID0gInJlZ3Jlc3Npb24iKSAlPiUKICBzZXRfZW5naW5lKCJyYW5kb21Gb3Jlc3QiKSAlPiUKICBzZXRfbW9kZSgicmVncmVzc2lvbiIpCiAgICAKCnR1bmVfUkZfbW9kZWwKCmBgYAoKCkFnYWluIHdlIHdpbGwgYWRkIHRoaXMgdG8gYSB3b3JrZmxvdywgdGhlIG9ubHkgZGlmZmVyZW5jZSBoZXJlIGlzIHRoYXQgd2UgYXJlIHVzaW5nIGEgZGlmZmVyZW50IG1vZGVsIHNwZWNpZmljYXRpb24gd2l0aCBgdHVuZV9SRl9tb2RlbGAgaW5zdGVhZCBvZiBgUkZfbW9kZWxgOgoKYGBge3J9CgpSRl90dW5lX3dmbG93IDwtIHdvcmtmbG93czo6d29ya2Zsb3coKSAlPiUKICAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfcmVjaXBlKFJGX3JlYykgJT4lCiAgICAgICAgICAgIHdvcmtmbG93czo6YWRkX21vZGVsKHR1bmVfUkZfbW9kZWwpClJGX3R1bmVfd2Zsb3cKCmBgYAoKCk5vdyB3ZSBjYW4gdXNlIHRoZSBgdHVuZV9ncmlkKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSB0byBldmFsdWF0ZSBkaWZmZXJlbnQgY29tYmluYXRpb25zIG9mIHZhbHVlcyBmb3IgYG10cnlgIGFuZCBgbWluX25gIHVzaW5nIG91ciBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgb2Ygb3VyIHRyYWluaW5nIHNldCAoYHZmb2xkX3BtYCkgdG8gc2VlIHdoYXQgY29tYmluYXRpb24gb2YgdmFsdWVzIHBlcmZvcm1zIGJlc3QuCgpUbyB1c2UgdGhpcyBmdW5jdGlvbiB3ZSB3aWxsIHNwZWNpZnkgdGhlIHdvcmtmbG93IHVzaW5nIHRoZSBgb2JqZWN0YCBhcmd1bWVudCAgYW5kIHRoZSBzYW1wbGVzIHRvIHVzZSB1c2luZyB0aGUgYHJlc2FtcGxlc2AgYXJndW1lbnQuIFRoZSBgZ3JpZGAgYXJndW1lbnQgc3BlY2lmaWVzIGhvdyBtYW55IHBvc3NpYmxlIG9wdGlvbnMgZm9yIGVhY2ggYXJndW1lbnQgc2hvdWxkIGJlIGF0dGVtcHRlZC4KCkJ5IGRlZmF1bHQgMTAgZGlmZmVyZW50IHZhbHVlcyB3aWxsIGJlIGF0dGVtcHRlZCBmb3IgZWFjaCBoeXBlcnBhcmFtZXRlciB0aGF0IGlzIGJlaW5nIHR1bmVkLgoKV2UgY2FuIHVzZSB0aGUgYGRvUGFyYWxsZWxgIHBhY2thZ2UgdG8gYWxsb3cgdXMgdG8gZml0IGFsbCB0aGVzZSBtb2RlbHMgdG8gb3VyIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBmYXN0ZXIuIFNvIGlmIHlvdSB3ZXJlIHBlcmZvcm1pbmcgdGhpcyBvbiBhIGNvbXB1dGVyIHdpdGggbXVsdGlwbGUgY29yZXMgb3IgcHJvY2Vzc29ycywgdGhlbiBkaWZmZXJlbnQgbW9kZWxzIHdpdGggZGlmZmVyZW50IGh5cGVycGFyYW1ldGVyIHZhbHVlcyBjYW4gYmUgZml0IHRvIHRoZSBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgc2ltdWx0YW5lb3VzbHkgYWNyb3NzIGRpZmZlcmVudCBjb3JlcyBvciBwcm9jZXNzb3JzLiAKCllvdSBjYW4gc2VlIGhvdyBtYW55IGNvcmVzIHlvdSBoYXZlIGFjY2VzcyB0byBvbiB5b3VyIHN5c3RlbSB1c2luZyB0aGUgYGRldGVjdENvcmVzKClgIGZ1bmN0aW9uIGluIHRoZSBgcGFyYWxsZWxgIHBhY2thZ2UuIAoKYGBge3J9CnBhcmFsbGVsOjpkZXRlY3RDb3JlcygpCmBgYAoKVGhlIGByZWdpc3RlckRvUGFyYWxsZWwoKWAgZnVuY3Rpb24gd2lsbCB1c2UgdGhlIG51bWJlciBmb3IgY29yZXMgc3BlY2lmaWVkIHVzaW5nIHRoZSBgY29yZXM9YCBhcmd1ZW1lbnQsIG9yIGl0IHdpbGwgYXNzaWduIGl0IGF1dG9tYXRpY2FsbHkgdG8gb25lLWhhbGYgb2YgdGhlIG51bWJlciBvZiBjb3JlcyBkZXRlY3RlZCBieSB0aGUgYHBhcmFsbGVsYCBwYWNrYWdlLiAKCldlIG5lZWQgdG8gdXNlIGBzZXQuc2VlZCgpYCBoZXJlIGJlY2F1c2UgdGhlIHZhbHVlcyBjaG9zZW4gZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCBtYXkgdmFyeSBpZiB3ZSBwcmVmb3JtIHRoaXMgZXZhbHVhdGlvbiBhZ2FpbiBiZWNhdXNlIHRoZXkgYXJlIGNob3NlbiBzZW1pLXJhbmRvbWx5IChtZWFuaW5nIHRoYXQgdGhleSBhcmUgd2l0aGluIGEgcmFuZ2Ugb2YgcmVhc29uYWJsZSB2YWx1ZXMgYnV0IHN0aWxsIHJhbmRvbSkuCgpOb3RlOiB0aGlzIHN0ZXAgd2lsbCB0YWtlIHNvbWUgdGltZS4KCmBgYHtyfQpkb1BhcmFsbGVsOjpyZWdpc3RlckRvUGFyYWxsZWwoY29yZXM9MikKc2V0LnNlZWQoMTIzKQp0dW5lX1JGX3Jlc3VsdHMgPC0gdHVuZV9ncmlkKG9iamVjdCA9IFJGX3R1bmVfd2Zsb3csIHJlc2FtcGxlcyA9IHZmb2xkX3BtLCBncmlkID0gMjApCnR1bmVfUkZfcmVzdWx0cwpgYGAKCgpTZWUgW3RoZSB0dW5lIGdldHRpbmcgc3RhcnRlZCBndWlkZSBdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vdHVuZS9hcnRpY2xlcy9nZXR0aW5nX3N0YXJ0ZWQuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBpbXBsZW1lbnRpbmcgdGhpcyBpbiBgdGlkeW1vZGVsc2AuCgpJZiB5b3Ugd2FudGVkIG1vcmUgY29udHJvbCBvdmVyIHRoaXMgcHJvY2VzcyB5b3UgY291bGQgc3BlY2lmeSBob3cgdGhlIGRpZmZlcmVudCBwb3NzaWJsZSBvcHRpb25zIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgaW4gdGhlIGB0dW5lX2dyaWQoKWAgZnVuY3Rpb24gdXNpbmcgdGhlIGBncmlkXyooKWAgZnVuY3Rpb25zIG9mIHRoZSBgZGlhbHNgIHBhY2thZ2UgdG8gY3JlYXRlIGEgbW9yZSBzcGVjaWZpYyBncmlkLgoKQmUgZGVmYXVsdCB0aGUgdmFsdWVzIGZvciB0aGUgaHlwZXJwYXJhbWV0ZXJzIGJlaW5nIHR1bmVkIGFyZSBjaG9zZW4gc2VtaS1yYW5kb21seSAobWVhbmluZyB0aGF0IHRoZXkgYXJlIHdpdGhpbiBhIHJhbmdlIG9mIHJlYXNvbmFibGUgdmFsdWVzIGJ1dCBzdGlsbCByYW5kb20pLi4KCgpOb3cgd2UgY2FuIHVzZSB0aGUgYGNvbGxlY3RfbWV0cmljcygpYCBmdW5jdGlvbiBhZ2FpbiB0byB0YWtlIGEgbG9vayBhdCB3aGF0IGhhcHBlbmVkIHdpdGggb3VyIGNyb3NzIHZhbGlkYXRpb24gdGVzdHMuIFdlIGNhbiBzZWUgdGhlIGRpZmZlcmVudCB2YWx1ZXMgY2hvc2VuIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgYW5kIHRoZSBtZWFuIHJtc2UgYW5kIHJzcSB2YWx1ZXMgYWNyb3NzIHRoZSBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMuCgpgYGB7cn0KdHVuZV9SRl9yZXN1bHRzJT4lCiAgY29sbGVjdF9tZXRyaWNzKCkKYGBgCgpXZSBjYW4gbm93IHVzZSB0aGUgYHNob3dfYmVzdCgpYCBmdW5jdGlvbiBhcyBpdCB3YXMgdHJ1bHkgaW50ZW5kZWQsIHRvIHNlZSB3aGF0IHZhbHVlcyBmb3IgYG1pbl9uYCBhbmQgYG10cnlgIHJlc3VsdGVkIGluIHRoZSBiZXN0IHBlcmZvcm1hbmNlLgoKYGBge3J9CnNob3dfYmVzdCh0dW5lX1JGX3Jlc3VsdHMsIG1ldHJpYyA9ICJybXNlIiwgbiA9MSkKYGBgClRoZXJlIHdlIGhhdmUgaXQuLi4gbG9va3MgbGlrZSBhbiBgbXRyeWAgb2YgMTcgYW5kIGBtaW5fbmAgb2YgNCBoYWQgdGhlIGJlc3QgYHJtc2VgIHZhbHVlLiBZb3UgY2FuIHZlcmlmeSB0aGlzIGluIHRoZSBhYm92ZSBvdXRwdXQsIGJ1dCBpdCBpcyBlYXNpZXIgdG8ganVzdCBwdWxsIHRoaXMgcm93IG91dCB1c2luZyB0aGlzIGZ1bmN0aW9uLiBXZSBjYW4gc2VlIHRoYXQgdGhlIG1lYW4gYHJtc2VgIHZhbHVlIGFjcm9zcyB0aGUgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzIHdhcyAxLjcxMi4gQmVmb3JlIHR1bmluZyBpdCB3YXMgMS43MjUgIHdpdGggYSBzaW1pbGFyIGBzdGRfZXJyYCBzbyB0aGUgcGVyZm9ybWFuY2Ugd2FzIHZlcnkgc2xpZ2h0bHkgaW1wcm92ZWQuCgoKIyMgRmluYWwgbW9kZWwgcGVyZm9ybWFuY2UgZXZhbHVhdGlvbgoKTm93IHRoYXQgd2UgaGF2ZSBkZWNpZGVkIHRoYXQgd2UgaGF2ZSByZWFzb25hYmxlIHBlcmZvcm1hbmNlIHdpdGggb3VyIHRyYWluaW5nIGRhdGEsIHdlIGNhbiBzdG9wIGJ1aWxkaW5nIG91ciBtb2RlbCBhbmQgZXZhbHVhdGUgcGVyZm9ybWFuY2Ugd2l0aCBvdXIgdGVzdGluZyBkYXRhLiAKCkhlcmUsIHdlIHdpbGwgdXNlIHRoZSByYW5kb20gZm9yZXN0IG1vZGVsIHRoYXQgd2UgYnVpbHQgdG8gcHJlZGljdCB2YWx1ZXMgZm9yIHRoZSBtb25pdG9ycyBpbiB0aGUgdGVzdGluZyBkYXRhIGFuZCB3ZSB3aWxsIHVzZSB0aGUgdmFsdWVzIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgdGhhdCB3ZSBqdXN0IGRldGVybWluZWQgYmFzZWQgb24gb3VyIHR1bmluZyBhbmFseXNpcyB0byBhY2hpZXZlIHRoZSBiZXN0IHBlcmZvcm1hbmNlLgoKU28sIGZpcnN0IHdlIG5lZWQgdG8gc3BlY2lmeSB0aGVzZSB2YWx1ZXMgaW4gYSB3b3JrZmxvdy4gV2UgY2FuIHVzZSB0aGUgYHNlbGVjdF9iZXN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSB0byBncmFiIHRoZSB2YWx1ZXMgdGhhdCB3ZXJlIGRldGVybWluZWQgdG8gYmUgYmVzdCBmb3IgYG10cnlgIGFuZCBgbWluX25gLgoKCgpgYGB7cn0KCnR1bmVkX1JGX3ZhbHVlczwtIHNlbGVjdF9iZXN0KHR1bmVfUkZfcmVzdWx0cywgInJtc2UiKQp0dW5lZF9SRl92YWx1ZXMKYGBgCgpOb3cgd2UgY2FuIGZpbmFsaXplIHRoZSBtb2RlbC93b3JrZmxvdyB0aGF0IHdlIHdlIHVzZWQgZm9yIHR1bmluZyB3aXRoIHRoZXNlIHZhbHVlcy4KCgpgYGB7cn0KUkZfdHVuZWRfd2Zsb3cgPC1SRl90dW5lX3dmbG93ICU+JQogIHR1bmU6OmZpbmFsaXplX3dvcmtmbG93KHR1bmVkX1JGX3ZhbHVlcykKYGBgCgoKV2l0aCB0aGUgYHdvcmtmbG93c2AgcGFja2FnZSwgd2UgY2FuIHVzZSB0aGUgc3BsaXR0aW5nIGluZm9ybWF0aW9uIGZvciBvdXIgb3JpZ2luYWwgZGF0YSBgcG1fc3BsaXRgIHRvIGZpdCB0aGUgZmluYWwgbW9kZWwgb24gdGhlIGZ1bGwgdHJhaW5pbmcgc2V0IGFuZCBhbHNvIG9uIHRoZSB0ZXN0aW5nIGRhdGEgdXNpbmcgdGhlIGBsYXN0X2ZpdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UuIE5vIHByZS1wcm9jZXNzaW5nIHN0ZXBzIGFyZSByZXF1aXJlZC4KClRoZSByZXN1bHRzIHdpbGwgc2hvdyB0aGUgcGVyZm9ybWFuY2UgdXNpbmcgdGhlIHRlc3RpbmcgZGF0YS4KCgpgYGB7cn0Kb3ZlcmFsbGZpdCA8LXR1bmU6Omxhc3RfZml0KFJGX3R1bmVkX3dmbG93LCBwbV9zcGxpdCkKICMgb3IKb3ZlcmFsbGZpdCA8LVJGX3dmbG93ICU+JQogIHR1bmU6Omxhc3RfZml0KHBtX3NwbGl0KQpgYGAKClRoZSBgb3ZlcmFsbGZpdGAgb3V0cHV0IGhhcyBhIGxvdCBvZiByZWFsbHkgdXNlZnVsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtb2RlbCwgdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIGRhdGEgc3BsaXQsIGFuZCB0aGUgcHJlZGljdGlvbnMgZm9yIHRoZSB0ZXN0aW5nIGRhdGEuCgpUbyBzZWUgdGhlIHBlcmZvcm1hbmNlIG9uIHRoZSB0ZXN0IGRhdGEgd2UgY2FuIHVzZSB0aGUgYGNvbGxlY3RfbWV0cmljcygpYCBmdW5jdGlvbiBsaWtlIHdlIGRpZCBiZWZvcmUuCmBgYHtyfQogIGNvbGxlY3RfbWV0cmljcyhvdmVyYWxsZml0KQogCmBgYAoKQXdlc29tZSEgV2UgY2FuIHNlZSB0aGF0IG91ciBybXNlIG9mIDEuNDQgaXMgcXVpdGUgc2ltaWxhciB3aXRoIG91ciB0ZXN0aW5nIGRhdGEgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzLiBXZSBhY2hpZXZlZCBxdWl0ZSBnb29kIHBlcmZvcm1hbmNlLCB3aGljaCBzdWdnZXN0cyB0aGF0IHdlIHdvdWxkIGNvdWxkIHByZWRpY3Qgb3RoZXIgbG9jYXRpb25zIHdpdGggbW9yZSBzcGFyc2UgbW9uaXRvcmluZyBiYXNlZCBvbiBvdXIgcHJlZGljdG9ycyB3aXRoIHJlYXNvbmFibGUgYWNjdXJhY3kuCgpOb3cgaWYgeW91IHdhbnRlZCB0byB0YWtlIGEgbG9vayBhdCB0aGUgcHJlZGljdGVkIHZhbHVlcyBmb3IgdGhlIHRlc3Qgc2V0ICh0aGUgMjkyIHJvd3Mgd2l0aCBwcmVkaWN0aW9ucyBvdXQgb2YgdGhlIDg3NiBvcmlnaW5hbCBtb25pdG9yIHZhbHVlcykgeW91IGNhbiB1c2UgdGhlICBgY29sbGVjdF9wcmVkaWN0aW9ucygpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmUoKWAgcGFja2FnZToKCmBgYHtyfQp0ZXN0X3ByZWRpY3Rpb25zIDwtY29sbGVjdF9wcmVkaWN0aW9ucyhvdmVyYWxsZml0KQpgYGAKCmBgYHtyLCBldmFsID0gRkFMU0V9CnRlc3RfcHJlZGljdGlvbnMKYGBgCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyLCBlY2hvID1GQUxTRX0KdGVzdF9wcmVkaWN0aW9ucyAlPiUKICBwcmludChuID0gMWUzKQpgYGAKCiMjIyMKCk5pY2UhCgojICoqRGF0YSBWaXN1YWxpemF0aW9uKioKKioqCgpPdXIgbWFpbiBxdWVzdGlvbiBmb3IgdGhpcyBjYXNlIHN0dWR5IHdhczogIAoKPiBDYW4gd2UgcHJlZGljdCBhbm51YWwgYXZlcmFnZSBhaXIgcG9sbHV0aW9uIGNvbmNlbnRyYXRpb25zIGF0IHRoZSBncmFudWxhcml0eSBvZiB6aXAgY29kZSByZWdpb25hbCBsZXZlbHMgdXNpbmcgcHJlZGljdG9ycyBzdWNoIGFzIGRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5LCB1cmJhbml6YXRpb24sIHJvYWQgZGVuc2l0eSwgYXMgd2VsbCBhcywgc2F0ZWxsaXRlIHBvbGx1dGlvbiBkYXRhIGFuZCBjaGVtaWNhbCBtb2RlbGluZyBkYXRhPwoKVGh1cyBmYXIsIHdlIGhhdmUgYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIChNTCkgbW9kZWwgdG8gcHJlZGljdCBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciBhaXIgcG9sbHV0aW9uIGxldmVscyBiYXNlZCBvbiBvdXIgcHJlZGljdG9yIHZhcmlhYmxlcyAob3IgZmVhdHVyZXMpLgoKTm93LCBsZXQncyBtYWtlIGEgcGxvdCBvZiBvdXIgcHJlZGljdGVkIG91dGNvbWUgdmFsdWVzICgkXGhhdHtZfSQpIGFuZCBhY3R1YWwgb3V0Y29tZSB2YWx1ZXMgJFkkIHdlIG9ic2VydmVkLiAKCkZpcnN0LCBsZXQncyBzdGFydCBieSBtYWtpbmcgYSBwbG90IG9mIG91ciBtb25pdG9ycy4gClRvIGRvIHRoaXMsIHdlIHdpbGwgdXNlIHRoZSBmb2xsb3dpbmcgcGFja2FnZXMgdG8gY3JlYXRlIGEgbWFwIG9mIHRoZSBVUzoKCjEuIGBzZmAgLSB0aGUgc2ltcGxlIGZlYXR1cmVzIHBhY2thZ2UgaGVscHMgdG8gY29udmVydCBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMgaW50byBgZ2VvbWV0cnlgIHZhcmlhYmxlcyB3aGljaCBhcmUgdXNlZnVsIGZvciBtYWtpbmcgMkQgcGxvdHMKMi4gYG1hcHNgIC0gdGhpcyBwYWNrYWdlIGNvbnRhaW5zIGdlb2dyYXBoaWNhbCBvdXRsaW5lcyBhbmQgcGxvdHRpbmcgZnVuY3Rpb25zIHRvIGNyZWF0ZSBwbG90cyB3aXRoIG1hcHMgCjMuIGBybmF0dXJhbGVhcnRoYC0gdGhpcyBhbGxvd3MgZm9yIGVhc3kgaW50ZXJhY3Rpb24gd2l0aCBtYXAgZGF0YSBmcm9tIFtOYXR1cmFsIEVhcnRoXShodHRwOi8vd3d3Lm5hdHVyYWxlYXJ0aGRhdGEuY29tLykgd2hpY2ggaXMgYSBwdWJsaWMgZG9tYWluIG1hcCBkYXRhc2V0CjQuIGByZ2Vvc2AgLSB0aGlzIHBhY2thZ2UgaW50ZXJmYWNlcyB3aXRoIHRoZSBHZW9tZXRyeSBFbmdpbmUtT3BlbiBTb3VyY2UgKGBHRU9TYCkgd2hpY2ggaXMgYWxzbyBoZWxwZnVsIGZvciBjb29yZGluYXRlIGNvbnZlcnNpb24KCldlIHdpbGwgc3RhcnQgd2l0aCBnZXR0aW5nIGFuIG91dGxpbmUgb2YgdGhlIFVTIHdpdGggdGhlIGBuZV9jb3VudHJpZXMoKWAgZnVuY3Rpb24gb2YgdGhlIGBybmF0dXJhbGVhcnRoYCBwYWNrYWdlIHdoaWNoIHdpbGwgcmV0dXJuIHBvbHlnb25zIG9mIHRoZSBjb3VudHJpZXMgaW4gdGhlIFtOYXR1cmFsIEVhcnRoXShodHRwOi8vd3d3Lm5hdHVyYWxlYXJ0aGRhdGEuY29tLykgZGF0YXNldC4KCmBgYHtyfQoKd29ybGQgPC0gbmVfY291bnRyaWVzKHNjYWxlID0gIm1lZGl1bSIsIHJldHVybmNsYXNzID0gInNmIikKZ2xpbXBzZSh3b3JsZCkKCmBgYAoKCkhlcmUgeW91IGNhbiBzZWUgdGhlIGRhdGEgYWJvdXQgdGhlIGNvdW50cmllcyBpbiB0aGUgd29ybGQuIE5vdGljZSB0aGUgYGdlb21ldHJ5YCB2YXJpYWJsZS4gVGhpcyBpcyB1c2VkIHRvIGNyZWF0ZSB0aGUgb3V0bGluZXMgdGhhdCB3ZSB3YW50LiAKCk5vdyB3ZSBjYW4gdXNlIHRoZSBgZ2VvbV9zZigpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UgdG8gY3JlYXRlIGEgdmlzdWFsIG9mIHNpbXBsZSBmZWF0dXJlICh0aGUgZ2VvbWV0cnkgY29vcmRpbmF0ZXMgZm91bmQgaW4gdGhlIGBnZW9tZXRyeWAgdmFyaWFibGUpLgoKYGBge3J9CmdncGxvdChkYXRhID0gd29ybGQpICsKICAgIGdlb21fc2YoKSAKCmBgYAoKU28gbm93IHdlIGNhbiBzZWUgdGhhdCB3ZSBoYXZlIG91dGxpbmVzIG9mIGFsbCB0aGUgY291bnRyaWVzIGluIHRoZSB3b3JsZC4KCldlIHdhbnQgdG8gbGltaXQgdGhpcyBqdXN0IHRvIHRoZSBjb29yZGluYXRlcyBmb3IgdGhlIFVTLiBXZSB3aWxsIGRvIHRoaXMgYmFzZWQgb24gdGhlIGNvb3JkaW5hdGVzIHdlIGZvdW5kIG9uIFdpa2lwZWRpYS4gQWNjb3JkaW5nIHRvIHRoaXMgW2xpbmtdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xpc3Rfb2ZfZXh0cmVtZV9wb2ludHNfb2ZfdGhlX1VuaXRlZF9TdGF0ZXMjV2VzdGVybm1vc3Qpe3RhcmdldD0iX2JsYW5rIn0sIHRoZXNlIGFyZSB0aGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBib3VuZHMgb2YgdGhlIGNvbnRpbmVudGFsIFVTOgoKLSB0b3AgPSA0OS4zNDU3ODY4ICMgbm9ydGggbGF0Ci0gbGVmdCA9IC0xMjQuNzg0NDA3OSAjIHdlc3QgbG9uZwotIHJpZ2h0ID0gLTY2Ljk1MTM4MTIgIyBlYXN0IGxvbmcKLSBib3R0b20gPSAgMjQuNzQzMzE5NSAjIHNvdXRoIGxhdAoKYGBge3J9CgpnZ3Bsb3QoZGF0YSA9IHdvcmxkKSArCiAgICBnZW9tX3NmKCkgKwogICAgY29vcmRfc2YoeGxpbSA9IGMoLTEyNSwgLTY2KSwgeWxpbSA9IGMoMjQuNSwgNTApLCAKICAgICAgICAgICAgIGV4cGFuZCA9IEZBTFNFKQpgYGAKTm93IHdlIGp1c3QgaGF2ZSBhIHBsb3QgdGhhdCBpcyBtb3N0bHkgbGltaXRlZCB0byB0aGUgb3V0bGluZSBvZiB0aGUgVVMuCgpOb3cgd2Ugd2lsbCB1c2UgdGhlIGBnZW9tX3BvaW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90YCBwYWNrYWdlIHRvIGFkZCBzY2F0dGVyIHBsb3Qgb24gdG9wIG9mIHRoZSBtYXAuIFdlIHdhbnQgdG8gc2hvdyB3aGVyZSB0aGUgbW9uaXRvcnMgYXJlIGxvY2F0ZWQgYmFzZWQgb24gdGhlIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgdmFsdWVzIGluIHRoZSBkYXRhLgoKYGBge3J9CmdncGxvdChkYXRhID0gd29ybGQpICsKICAgIGdlb21fc2YoKSArCiAgICBjb29yZF9zZih4bGltID0gYygtMTI1LCAtNjYpLCB5bGltID0gYygyNC41LCA1MCksIAogICAgICAgICAgICAgZXhwYW5kID0gRkFMU0UpKwogICAgZ2VvbV9wb2ludChkYXRhID0gcG0sIGFlcyh4ID0gbG9uLCB5ID0gbGF0KSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgICBzaGFwZSA9IDIzLCBmaWxsID0gImRhcmtyZWQiKQoKYGBgCk5pY2UhCgpOb3cgbGV0J3MgYWRkIGNvdW50eSBsaW5lcy4KCkNvdW50eSBncmFwaGljYWwgZGF0YSBpcyBhdmFpbGFibGUgZnJvbSB0aGUgYG1hcHNgIHBhY2thZ2UuIApUaGUgYHNmYCBwYWNrYWdlIHdoaWNoIGFnYWluIGlzIHNob3J0IGZvciBzaW1wbGUgZmVhdHVyZXMgY3JlYXRlcyBhIGRhdGEgZnJhbWUgYWJvdXQgdGhpcyBncmFwaGljYWwgZGF0YSBzbyB0aGF0IHdlIGNhbiB3b3JrIHdpdGggaXQuCgpgYGB7cn0KY291bnRpZXMgPC0gCiAgc2Y6OnN0X2FzX3NmKG1hcHM6Om1hcCgiY291bnR5IiwgcGxvdCA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBUUlVFKSkKCmNvdW50aWVzCmBgYAoKTm93IHdlIHdpbGwgdXNlIHRoaXMgZGF0YSB3aXRoaW4gdGhlIGBnZW9tX3NmKClgIGZ1bmN0aW9uIHRvIGFkZCB0aGlzIHRvIG91ciBwbG90LiAgV2Ugd2lsbCBhbHNvIGFkZCBhIHRpdGxlIHVzaW5nIHRoZSBgZ2d0aXRsZSgpYCBmdW5jdGlvbiwgYXMgd2VsbCBhcyByZW1vdmUgYXhpcyB0aWNrcyBhbmQgdGl0bGVzIHVzaW5nIHRoZSBgdGhlbWUoKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlLgoKYGBge3J9Cm1vbml0b3JzIDwtIGdncGxvdChkYXRhID0gd29ybGQpICsKICAgIGdlb21fc2YoZGF0YSA9IGNvdW50aWVzLCBmaWxsID0gTkEsIGNvbG9yID0gZ3JheSguNSkpKwogICAgICBjb29yZF9zZih4bGltID0gYygtMTI1LCAtNjYpLCB5bGltID0gYygyNC41LCA1MCksIAogICAgICAgICAgICAgZXhwYW5kID0gRkFMU0UpICsKICAgIGdlb21fcG9pbnQoZGF0YSA9IHBtLCBhZXMoeCA9IGxvbiwgeSA9IGxhdCksIHNpemUgPSAyLCAKICAgICAgICAgICAgICAgc2hhcGUgPSAyMywgZmlsbCA9ICJkYXJrcmVkIikgKwogICAgZ2d0aXRsZSgiTW9uaXRvciBMb2NhdGlvbnMiKSArCiAgICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpCgptb25pdG9ycwpgYGAKCkdyZWF0IQoKTm93LCBsZXQncyBhZGQgYSBmaWxsIGF0IHRoZSBjb3VudHktbGV2ZWwgZm9yIHRoZSB0cnVlIG1vbml0b3IgdmFsdWVzIG9mIGFpciBwb2xsdXRpb24uCgpGaXJzdCwgd2UgbmVlZCB0byBnZXQgdGhlIGNvdW50eSBtYXAgZGF0YSB0aGF0IHdlIGp1c3QgZ290IGFuZCBvdXIgYWlyIHBvbGx1dGlvbiBkYXRhIHRvIGhhdmUgc2ltaWxhcmx5IGZvcm1hdHRlZCBjb3VudHkgbmFtZXMgc28gdGhhdCB3ZSBjYW4gY29tYmluZSB0aGUgZGF0YXNldHMgdG9nZXRoZXIuCgpXZSBjYW4gc2VlIHRoYXQgaW4gdGhlIGBjb3VudHlgIGRhdGEgdGhlIGNvdW50aWVzIGFyZSBsaXN0ZWQgYWZ0ZXIgdGhlIHN0YXRlIG5hbWUgYW5kIGEgY29tbWEuIEluIGFkZGl0aW9uIHRoZXkgYXJlIGFsbCBsb3dlciBjYXNlLgoKCmBgYHtyfQpoZWFkKGNvdW50aWVzKQpgYGAKCkluIGNvbnRyYXN0LCBvdXIgYWlyIHBvbGx1dGlvbiBgcG1gIGRhdGEgc2hvd3MgY291bnRpZXMgYXMgdGl0bGVzIHdpdGggdGhlIGZpcnN0IGxldHRlciBhcyB1cHBlciBjYXNlLiAKCmBgYHtyfQpkcGx5cjo6cHVsbChwbSwgY291bnR5KSAlPiUKICBoZWFkKCkKYGBgCgpXZSBjYW4gdXNlIHRoZSBgc2VwYXJhdGUoKWAgZnVuY3Rpb24gb2YgdGhlIGB0aWR5cmAgcGFja2FnZSB0byBzZXBhcmF0ZSB0aGUgYElEYCB2YXJpYWJsZSBvZiBvdXIgYGNvdW50aWVzYCBkYXRhIGludG8gdHdvIGB2YXJpYWJsZXNgIGJhc2VkIG9uIHRoZSBjb21tYSBhcyBhIHNlcGFyYXRvci4KCmBgYHtyfQpjb3VudGllcyAlPD4lIAogIHRpZHlyOjpzZXBhcmF0ZShJRCwgaW50byA9IGMoInN0YXRlIiwgImNvdW50eSIpLCBzZXAgPSAiLCIpCgpoZWFkKGNvdW50aWVzKQpgYGAKTm93IHdlIGp1c3QgbmVlZCB0byBtYWtlIHRoZXNlIG5hbWVzIGluIHRoZSBuZXcgYGNvdW50eWAgdmFyaWFibGUgb2YgdGhlIGBjb3VudGllc2AgZGF0YSB0byBiZSBpbiB0aXRsZSBmb3JtYXQuIFdlIGNhbiB1c2UgdGhlIGBzdHJfdG9fdGl0bGUoKWAgZnVuY3Rpb24gb2YgdGhlIGBzdHJpbmdyYCBwYWNrYWdlIHRvIGRvIHRoaXMuIApgYGB7cn0KY291bnRpZXNbWyJjb3VudHkiXV0gPC0gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKGNvdW50aWVzW1siY291bnR5Il1dKQpgYGAKCkdyZWF0ISBOb3cgdGhlIGNvdW50eSBpbmZvcm1hdGlvbiBpcyB0aGUgc2FtZSBmb3IgdGhlIGBjb3VudGllc2AgYW5kIGBwbWAgZGF0YS4KCldlIGNhbiB1c2UgdGhlIGBpbm5lcl9qb2luKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gam9pbiB0aGUgZGF0YXNldHMgdG9nZXRoZXIgYmFzZWQgb24gdGhlIGBjb3VudHlgIHZhcmlhYmxlcyBpbiBlYWNoLiBUaGlzIGZ1bmN0aW9uIHdpbGwga2VlcCBhbGwgcm93cyB0aGF0IGFyZSBpbiBib3RoIGRhdGFzZXRzLgoKYGBge3J9Cm1hcF9kYXRhIDwtZHBseXI6OmlubmVyX2pvaW4oY291bnRpZXMsIHBtLCBieSA9ICJjb3VudHkiKQoKZ2xpbXBzZShtYXBfZGF0YSkKCmBgYApOaWNlISB3ZSBjYW4gc2VlIHRoYXQgd2UgaGF2ZSBhZGQgYSBgZ2VvbWAgdmFyaWFibGUgdG8gdGhlIGBwbWAgZGF0YS4KCk5vdyB3ZSBjYW4gdXNlIHRoaXMgdG8gY29sb3IgdGhlIGNvdW50aWVzIGluIG91ciBwbG90IGJhc2VkIG9uIHRoZSBgdmFsdWVgIHZhcmlhYmxlIG9mIG91ciBgcG1gIGRhdGEsIHdoaWNoIHlvdSBtYXkgcmVjYWxsIGlzIHRoZSBhY3R1YWwgbW9uaXRvciBkYXRhIGZvciBmaW5lIHBhcnRpY3VsYXRlIGFpciBwb2xsdXRpb24gYXQgZWFjaCBtb25pdG9yLiAKCldFIGNhbiBkbyBzbyB1c2luZyB0aGUgYHNjYWxlX2ZpbGxfZ3JhZGllbnRuKClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90MmAgcGFja2FnZSB3aGljaCBjcmVhdGVzIGNvbG9yIGdyYWRpZW50IGJhc2VkIG9uIGEgdmFyaWFibGUuIEluIHRoaXMgY2FzZSBpdCBpcyB0aGUgdmFyaWFibGUgdGhhdCB3YXMgc3BlY2lmaWVkIGFzIHRoZSBgZmlsbGAgaW4gdGhlIGBhZXNgIGZ1bmN0aW9uIG9mIHRoZSBgZ2VvbV9zZigpYCBmdW5jdGlvbi4gV2Ugc3BlY2lmaWVkIHRoYXQgaXQgd291bGQgYmUgdGhlIGB2YWx1ZWAgdmFyaWFibGUgb2YgdGhlIGBwbWAgZGF0YS4KClRoaXMgYHNjYWxlX2ZpbGxfZ3JhZGllbnRuKClgIGZ1bmN0aW9uICBhbHNvIGFsbG93cyB5b3UgdG8gc3BlY2lmeSB0aGUgY29sb3JzLCB3aGF0IHRvIGRvIGFib3V0IE5BIHZhbHVlcyAoc2hvdWxkIHRoZXkgYmUgYSBzcGVjaWZpYyBjb2xvciBvciB0cmFuc3BhcmVudCkgYW5kIHRoZSBicmVha3MsIGxpbWl0cywgbGFiZWxzIGFuZCBuYW1lL3RpdGxlIG9uIHRoZSBsZWdlbmQgZm9yIHRoZSBjb2xvciBncmFkaWVudC4gCgpgYGB7cn0KCnRydXRoIDwtZ2dwbG90KGRhdGEgPSB3b3JsZCkgKwogIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgZXhwYW5kID0gRkFMU0UpKwogICAgZ2VvbV9zZihkYXRhID0gbWFwX2RhdGEsIGFlcyhmaWxsID0gdmFsdWUpKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz10b3BvLmNvbG9ycyg3KSwgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3M9YygwLDEwLDIwKSxsYWJlbHM9YygwLDEwLDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwyMy41KSwgbmFtZSA9ICJQTSB1Zy9tMyIpICsKICBnZ3RpdGxlKCJUcnVlIFBNIDIuNSBsZXZlbHMiKSArCiAgICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpCgp0cnV0aAoKYGBgCk5pY2UhCgpOb3cgbGV0J3MgZG8gdGhlIHNhbWUgd2l0aCBvdXIgcHJlZGljdGVkIG91dGNvbWUgdmFsdWVzLgoKTGV0J3MgZ3JhYiBib3RoIHRoZSB0ZXN0aW5nIGFuZCB0cmFpbmluZyBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgc28gdGhhdCB3ZSBoYXZlIGFzIG11Y2ggZGF0YSBhcyBwb3NzaWJsZS4gCgpGaXJzdCB3ZSBuZWVkIHRvIGZpdCBvdXIgdHJhaW5pbmcgZGF0YSB3aXRoIG91ciBmaW5hbCBtb2RlbCB0byBiZSBhYmxlIHRvIGdldCB0aGUgcHJlZGljdGlvbnMgZm9yIHRoZSBtb25pdG9ycyBpbmNsdWRlZCBpbiB0aGUgdHJhaW5pbmcgc2V0LiBXZSBkaWQgdGhpcyB1c2luZyB0aGUgYGxhc3RfZml0KClgIGZ1bmN0aW9uLCBidXQgdGhlIG91dHB1dCBvZiB0aGlzIG1ha2VzIGl0IGRpZmZpY3VsdCB0byBncmFiIHRoZSBwcmVkaWN0ZWQgdmFsdWVzIGZvciB0aGUgdHJhaW5pbmcgZGF0YSwgYW5kIGl0IGlzIGFsc28gZGlmZmljdWx0IHRvIGdldCB0aGUgaWQgdmFyaWFibGVzIGZvciB0aGUgdGVzdGluZyBkYXRhLiAKCgpUaHVzIHdlIHdpbGwgdXNlIHRoZSBwYXJzbmlwIGBmaXQoKWAgYW5kIGBwcmVkaWN0KClgIGZ1bmN0aW9ucyBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UgdG8gZG8gdGhpcyBsaWtlIHNvOgoKIyMjIyB7LnRoaW5rX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4KCldoeSBkbyB3ZSBub3QgbmVlZCBwcmUtcHJvY2Vzc2VkIGRhdGE/CgojIyMjCgoqKioKCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5PgoKU2luY2Ugd2UgYXJlIHVzaW5nIGEgd29ya2Zsb3csIHRoZSBkYXRhIHdpbGwgYmUgcHJlLXByb2Nlc3NlZCB3aGVuIGl0IGlzIGZpdCBhcyB3ZWxsLgoKPC9kZXRhaWxzPgoqKioKCgpgYGB7cn0KClJGX2ZpbmFsX3RyYWluX2ZpdCA8LSBwYXJzbmlwOjpmaXQoUkZfdHVuZWRfd2Zsb3csIGRhdGEgPSB0cmFpbl9wbSkKUkZfZmluYWxfdGVzdF9maXQgPC0gcGFyc25pcDo6Zml0KFJGX3R1bmVkX3dmbG93LCBkYXRhID0gdGVzdF9wbSkKCgp2YWx1ZXNfcHJlZF90cmFpbiA8LSAKICBwcmVkaWN0KFJGX2ZpbmFsX3RyYWluX2ZpdCwgdHJhaW5fcG0pICU+JSAKICBiaW5kX2NvbHModHJhaW5fcG0gJT4lIHNlbGVjdCh2YWx1ZSwgZmlwcywgY291bnR5LCBpZCkpIAoKdmFsdWVzX3ByZWRfdHJhaW4KCnZhbHVlc19wcmVkX3Rlc3QgPC0gCiAgcHJlZGljdChSRl9maW5hbF90ZXN0X2ZpdCwgdGVzdF9wbSkgJT4lIAogIGJpbmRfY29scyh0ZXN0X3BtICU+JSBzZWxlY3QodmFsdWUsIGZpcHMsIGNvdW50eSwgaWQpKSAKCnZhbHVlc19wcmVkX3Rlc3QKYGBgCgpOb3cgd2UgY2FuIGNvbWJpbmUgdGhpcyBkYXRhIGZvciB0aGUgcHJlZGljdGlvbnMgZm9yIGFsbCBtb25pdG9ycyB1c2luZyB0aGUgYGJpbmRfcm93cygpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLCB3aGljaCB3aWxsIGVzc2VudGlhbGx5IGFwcGVuZCB0aGUgc2Vjb25kIGRhdGFzZXQgdG8gdGhlIGZpcnN0LgoKYGBge3J9CmFsbF9wcmVkIDwtIGJpbmRfcm93cyh2YWx1ZXNfcHJlZF90ZXN0LCB2YWx1ZXNfcHJlZF90cmFpbikKCmFsbF9wcmVkCmBgYAoKR3JlYXQhIGFzIHdlIGNhbiBzZWUgdGhlcmUgYXJlIDg3NiB2YWx1ZXMgbGlrZSB3ZSB3b3VsZCBleHBlY3QgZm9yIGFsbCBvZiB0aGUgbW9uaXRvcnMuIFdlIGNhbiB1c2UgdGhlIGBjb3VudHlgIHZhcmlhYmxlIHRvIGNvbWJpbmUgdGhpcyB3aXRoIHRoZSBgY291bnRpZXNgIGRhdGEgbGlrZSB3ZSBkaWQgd2l0aCB0aGUgYHBtYCBkYXRhIHByZXZpb3VzbHkgc28gdGhhdCB3ZSBjYW4gdXNlIHRoZSBgdmFsdWVgIHZhcmlhYmxlIGFzIGEgY29sb3Igc2NoZW1lIGZvciBvdXIgbWFwLgoKCmBgYHtyfQptYXBfZGF0YSA8LSBpbm5lcl9qb2luKGNvdW50aWVzLCBhbGxfcHJlZCwgYnkgPSAiY291bnR5IikKCnByZWQgPC0gZ2dwbG90KGRhdGEgPSB3b3JsZCkgKwogICAgICAgICAgY29vcmRfc2YoeGxpbSA9IGMoLTEyNSwgLTY2KSwgeWxpbSA9IGMoMjQuNSwgNTApLCAKICAgICAgICAgICAgICAgICBleHBhbmQgPSBGQUxTRSkgKwogICAgZ2VvbV9zZihkYXRhID0gbWFwX2RhdGEsIGFlcyhmaWxsID0gLnByZWQpKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz10b3BvLmNvbG9ycyg3KSwgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcz1jKDAsMTAsMjApLGxhYmVscz1jKDAsMTAsMjApLAogICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsMjMuNSksIG5hbWUgPSAiUE0gdWcvbTMiKSArCiAgZ2d0aXRsZSgiUHJlZGljdGVkIFBNIDIuNSBsZXZlbHMiKSsKICAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkKCnByZWQKYGBgCgpOb3cgd2Ugd2lsbCB1c2UgdGhlIGBwYXRjaHdvcmtgIHBhY2thZ2UgdG8gY29tYmluZSBvdXIgbGFzdCB0d28gcGxvdHMuIFRoaXMgYWxsb3dzIHVzIHRvIGNvbWJpbmUgcGxvdHMgdXNpbmcgdGhlIGArYCBvciB0aGUgYC9gIC4gVGhlIGArYCB3aWxsIHBsYWNlIHBsb3RzIHNpZGUgYnkgc2lkZSBhbmQgdGhlIGAvYCB3aWxsIHBsYWNlIHBsb3RzIHRvcCB0byBib3R0b20uCgoKTm93IGxldCdzIGp1c3QgY29tYmluZSB0aGUgdHJ1dGggcGxvdCBhbmQgdGhlIHByZWRpY3Rpb24gcGxvdHMgdG9nZXRoZXI6CmBgYHtyfQp0cnV0aC9wcmVkCgpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgcHJlZGljdGVkIGZpbmUgcGFydGljbGUgYWlyIHBvbGx1dGlvbiB2YWx1ZXMgaW4gKHVnL20zKSBhcmUgcXVpdGUgc2ltaWxhciB0byB0aGUgdHJ1ZSB2YWx1ZXMgbWVhc3VyZWQgYnkgdGhlIGFjdHVhbCBncmF2aW1ldHJpYyBtb25pdG9ycy4gV2UgY2FuIGFsc28gc2VlIHRoYXQgc291dGhlcm4gQ2FsaWZvcm5pYSBoYXMgc29tZSBsYXJnZSBjb3VudGllcyB3aXRoIHdvcnNlIHBvbGx1dGlvbiAoYXMgdGhleSBhcmUgeWVsbG93IGFuZCB0aHVzIGhhdmUgbXVjaCBoaWdoZXIgcGFydGljdWxhdGUgbWF0dGVyIGxldmVscykuCgpMZXQncyBhZGQgc29tZSB0ZXh0IHRvIG91ciBwbG90IHRvIGV4cGxhaW4gaXQgYSBiaXQgbW9yZS4gV2UgY2FuIGRvIHNvIHVzaW5nIHRoZSBgcGxvdF9hbm5vdGF0aW9uKClgIGZ1bmN0aW9uIG9mIHRoZSBgcGF0Y2h3b3JrYCBwYWNrYWdlLiBUaGUgYHRoZW1lYCBhcmd1bWVudCBvZiB0aGlzIGZ1bmN0aW9uIHRha2VzIHRoZSBzYW1lIHRoZW1lIGluZm9ybWF0aW9uIHVzaW5nIHRoZSBgdGhlbWUoKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlIGFzIHdoZW4gY3JlYXRpbmcgYGdncGxvdDJgcGxvdHMuCgpgYGB7cn0KKHRydXRoL3ByZWQpICsgcGxvdF9hbm5vdGF0aW9uKHRpdGxlID0gIk1hY2hpbmUgTGVhcm5pbmcgTWV0aG9kcyBBbGxvdyBmb3IgUHJlZGljdGlvbiBvZiBBaXIgUG9sbHV0aW9uIiwgc3VidGl0bGUgPSAiQSByYW5kb20gZm9yZXN0IG1vZGVsIHByZWRpY3RzIHRydWUgbW9uaXRvcmVkIGxldmVscyBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciAoUE0gMi41KSBhaXIgcG9sbHV0aW9uIGJhc2VkIG9uXG5kYXRhIGFib3V0IHBvcHVsYXRpb24gZGVuc2l0eSBhbmQgb3RoZXIgcHJlZGljdG9ycyByZWFzb25hYmx5IHdlbGwsIHRodXMgc3VnZ2VzdGluZyB0aGF0IHdlIGNhbiBwcmVkaWN0IGxldmVsc1xub2YgcG9sbHV0aW9uIGluIHBsYWNlcyB3aXRoIHBvb3IgbW9uaXRvcmluZyIsIHRoZW1lID0gdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0xMiwgZmFjZSA9ICJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSkKCmBgYAoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGV2YWw9RkFMU0V9CnBuZyhoZXJlOjpoZXJlKCJpbWciLCAibWFpbl9wbG90X21hcHMucG5nIiksIAogICAgaGVpZ2h0ID0gMTUwMCwgd2lkdGggPSAyMDAwLCByZXMgPSAzMDApCih0cnV0aC9wcmVkKSArIHBsb3RfYW5ub3RhdGlvbih0aXRsZSA9ICJNYWNoaW5lIExlYXJuaW5nIE1ldGhvZHMgQWxsb3cgZm9yIFByZWRpY3Rpb24gb2YgQWlyIFBvbGx1dGlvbiIsIHN1YnRpdGxlID0gIkEgcmFuZG9tIGZvcmVzdCBtb2RlbCBwcmVkaWN0cyB0cnVlIG1vbml0b3JlZCBsZXZlbHMgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgKFBNIDIuNSkgYWlyIHBvbGx1dGlvbiBiYXNlZCBvblxuZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIG90aGVyIHByZWRpY3RvcnMgcmVhc29uYWJseSB3ZWxsLCB0aHVzIHN1Z2dlc3RpbmcgdGhhdCB3ZSBjYW4gcHJlZGljdCBsZXZlbHNcbm9mIHBvbGx1dGlvbiBpbiBwbGFjZXMgd2l0aCBwb29yIG1vbml0b3JpbmciLCB0aGVtZSA9IHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9MTIsIGZhY2UgPSAiYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkpCmRldi5vZmYoKQpgYGAKCiMgKipTdW1tYXJ5KioKKioqCgojIyBTeW5vcHNpcwoKSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSBleHBsb3JlZCBncmF2aW1ldHJpYyBtb25pdG9yaW5nIGRhdGEgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgYWlyIHBvbGx1dGlvbiAob3V0Y29tZSB2YXJpYWJsZSkuIApPdXIgZ29hbCB3YXMgdG8gYWJsZSB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gd2hlcmUgd2Ugb25seSBoYWQgcHJlZGljdG9yIHZhcmlhYmxlcyAob3IgZmVhdHVyZXMpIHdpdGhvdXQgaGF2aW5nIG9ic2VydmVkIGEgY29ycmVzcG9uZGluZyBtZWFzdXJlbWVudCBvZiBhaXIgcG9sbHV0aW9uLgoKT3VyIGxlYXJuaW5nIG9iamVjdGl2ZXMgd2VyZTogCgotIEludHJvZHVjZSBjb25jZXB0cyBpbiBtYWNoaW5lIGxlYXJuaW5nCi0gRGVtb25zdHJhdGUgaG93IHRvIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyBtb2RlbCB3aXRoIGB0aWR5bW9kZWxzYAotIERlbW9uc3RyYXRlIGhvdyB0byB2aXN1YWxpemUgZ2VvLXNwYXRpYWwgZGF0YSB1c2luZyBgZ2dwbG90MmAKClVzaW5nIHRoZSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBidWlsdCBpbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIGNvdWxkIG5vdyBleHRlbmQgdGhpcyBtb2RlbCB0byBiZSB1c2VkIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBsZXZlbHMgaW4gYXJlYXMgd2l0aCBwb29yIG1vbml0b3JpbmcsIHRvIGhlbHAgaWRlbnRpZnkgcmVnaW9ucyB3aGVyZSBwb3B1bGF0aW9ucyBtYXliZSBlc3BlY2lhbGx5IGF0IHJpc2sgZm9yIHRoZSBoZWFsdGggZWZmZWN0cyBvZiBhaXIgcG9sbHV0aW9uLiAgCgpBbmFseXNlcyBsaWtlIHRoZSBvbmUgaW4gb3VyIGNhc2Ugc3R1ZHkgYXJlIGltcG9ydGFudCBmb3IgZGVmaW5pbmcgd2hpY2ggZ3JvdXBzIGNvdWxkIGJlbmVmaXQgdGhlIG1vc3QgZnJvbSBpbnRlcnZlbnRpb25zLCBlZHVjYXRpb24sIGFuZCBwb2xpY3kgY2hhbmdlcyB3aGVuIGF0dGVtcHRpbmcgdG8gbWl0aWdhdGUgcHVibGljIGhlYWx0aCBjaGFsbGVuZ2VzLiBZb3UgY2FuIHNlZSBpbiB0aGlzIFthcnRpY2xlXShodHRwczovL3d3dy5uZWptLm9yZy9kb2kvZnVsbC8xMC4xMDU2L05FSk1vYTE3MDI3NDcpe3RhcmdldD0iX2JsYW5rIn0gdGhhdCBtYW55IGFkZGl0aW9uYWwgY29uc2lkZXJhdGlvbnMgd291bGQgYmUgaW52b2x2ZWQgdG8gYWRlcXVhdGVseSB1bmRlcnN0YW5kIHRoZSBkYXRhIGVub3VnaCB0byByZWNvbW1lbmQgcG9saWN5IGNoYW5nZXMuCgoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIGhlcmUgZm9yIG1vcmUgb24gd2hhdCB3ZSBsZWFybmVkIHdpdGggYHRpZHltb2RlbHNgIDwvc3VtbWFyeT4KCkhlcmUsIHdlIHByb3ZpZGUgYW4gb3ZlcnZpZXcgb2YgdGhlIGB0aWR5bW9kZWxzYCBmcmFtZXdvcmsuIAoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJlY29zeXN0ZW0ucG5nIikpCmBgYAoKCldlIHBlcmZvcm1lZCB0aGUgbWFqb3Igc3RlcHMgb2YgbWFjaGluZSBsZWFybmluZyB0aGF0IHdlIGludHJvZHVjZWQgaW4gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF0YSBhbmFseXNpczogIAoKMS4gRGF0YSBleHBsb3JhdGlvbiAgCgpXZSB1c2VkIHBhY2thZ2VzIGxpa2UgYHNraW1yYCwgYHN1bW1hcnl0b29sc2AsIGBjb3JycGxvdGAsIGFuZCBgR0dhbGx5YCB0byBiZXR0ZXIgdW5kZXJzdGFuZCBvdXIgZGF0YS4gVGhlc2UgcGFja2FnZXMgZ2F2ZSBjYW4gdGVsbCB1cyBob3cgbWFueSBtaXNzaW5nIHZhbHVlcyBlYWNoIHZhcmlhYmxlIGhhcyAoaWYgYW55KSwgdGhlIGNsYXNzIG9mIGVhY2ggdmFyaWFibGUsIHRoZSBkaXN0cmlidXRpb24gb2YgdmFsdWVzIGZvciBlYWNoIHZhcmlhYmxlLCB0aGUgc3BhcnNpdHkgb2YgZWFjaCB2YXJpYWJsZSwgYW5kIHRoZSBsZXZlbCBvZiBjb3JyZWxhdGlvbiBiZXR3ZWVuIHZhcmlhYmxlcy4gIAoKMi4gRGF0YSBzcGxpdHRpbmcgCgpXZSB1c2VkIHRoZSBgcnNhbXBsZWAgcGFja2FnZSB0byBmaXJzdCBwZXJmb3JtIGFuIGluaXRpYWwgc3BsaXQgb2Ygb3VyIGRhdGEgaW50byB0d28gcGllY2VzOiBhIHRyYWluaW5nIHNldCBhbmQgYSB0ZXN0aW5nIHNldC4gVGhlIHRyYWluaW5nIHNldCB3YXMgdXNlZCB0byBvcHRpbWl6ZSB0aGUgbW9kZWwsIHdoaWxlIHRoZSB0ZXN0aW5nIHNldCB3YXMgdXNlZCBvbmx5IHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgZmluYWwgbW9kZWwuIFdlIGFsc28gdXNlZCB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgdG8gY3JlYXRlIGNyb3NzIHZhbGlkYXRpb24gc3Vic2V0cyBvZiBvdXIgdHJhaW5pbmcgZGF0YS4gVGhpcyBhbGxvd2VkIHVzIHRvIGJldHRlciBhc3Nlc3MgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciB0ZXN0ZWQgbW9kZWxzIHVzaW5nIG91ciB0cmFpbmluZyBkYXRhLiAgCgozLiBWYXJpYWJsZSBhc3NpZ25tZW50IGFuZCBwcmUtcHJvY2Vzc2luZyAgIAoKV2UgdXNlZCB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgdG8gYXNzaWduIHZhcmlhYmxlIHJvbGVzIChzdWNoIGFzIG91dGNvbWUsIHByZWRpY3RvciwgYW5kIGlkIHZhcmlhYmxlKS4gV2UgYWxzbyB1c2VkIHRoaXMgcGFja2FnZSB0byBjcmVhdGUgYSByZWNpcGUgZm9yIHByZS1wcm9jZXNzaW5nIG91ciB0cmFpbmluZyBhbmQgdGVzdGluZyBkYXRhLiBUaGlzIGludm9sdmVkIHN0ZXBzIHN1Y2ggYXM6IGAgc3RlcF9kdW1teWAgdG8gY3JlYXRlIGR1bW15IG51bWVyaWMgZW5jb2RpbmdzIG9mIG91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIGBzdGVwX2NvcnJgIHRvIHJlbW92ZSBoaWdobHkgY29ycmVsYXRlZCB2YXJpYWJsZXMsIGBzdGVwX256dmAgdG8gcmVtb3ZlIG5lYXIgemVybyB2YXJpYW5jZSB2YXJpYWJsZXMgdGhhdCB3b3VsZCBjb250cmlidXRlIGxpdHRsZSB0byBvdXIgbW9kZWwgYW5kIHBvdGVudGlhbGx5IGFkZCBub2lzZS4gIFdlIGxlYXJuZWQgdGhhdCBvbmNlIG91ciByZWNpcGUgd2FzIGNyZWF0ZWQgYW5kIHByZXBwZWQgdXNpbmcgYHByZXAoKWB3ZSBjb3VsZCBleHRyYWN0IHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgdXNpbmcgYGp1aWNlKClgIG9yIG91ciBwcmUtcHJvY2Vzc2VkIHRlc3RpbmcgZGF0YSB1c2luZyBgYmFrZSgpYC4gV2UgYWxzbyBsZWFybmVkIHRoYXQgaWYgd2UgdXNlZCB0aGUgbmV3ZXIgd29ya2Zsb3dzIHBhY2thZ2UgdGhhdCB3ZSBkaWQgbm90IG5lZWQgdG8gdGhlIGBwcmVwKClgLCBganVpY2UoKWAsIG9yIGBiYWtlKClgIGZ1bmN0aW9ucywgYnV0IHRoYXQgaXQgaXMgc3RpbGwgdXNlZnVsIHRvIGtub3cgaG93IHRvIGRvIHNvIGlmIHdlIHdhbnQgdG8gbG9vayBhdCBvdXIgZGF0YSBhbmQgaG93IHRoZSByZWNpcGUgaXMgaW5mbHVlbmNpbmcgaXQgbW9yZSBkZWVwbHkuICAKCjQuIE1vZGVsIHNwZWNpZmljYXRpb24sIGZpdHRpbmcsIHR1bmluZyBhbmQgcGVyZm9ybWFuY2UgZXZhbHVhdGlvbiB1c2luZyB0aGUgdHJhaW5pbmcgZGF0YSAgCgpXZSBsZWFybmVkIHRoYXQgdGhlIG1vZGVsIG5lZWRzIHRvIGZpcnN0IGJlIGZpdCB0byB0aGUgdHJhaW5pbmcgZGF0YS4gV2UgbGVhcm5lZCB0aGF0IGluIGJvdGggY2xhc3NpZmljYXRpb24gYW5kIHByZWRpY3Rpb24sIHRoZSBtb2RlbCBpcyBmaXQgdG8gdGhlIHRyYWluaW5nIGRhdGEgYW5kIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYXJlIHVzZWQgdG8gZXN0aW1hdGUgbnVtZXJpYyB2YWx1ZXMgKGluIHRoZSBjYXNlIG9mIHByZWRpY3Rpb24pIG9yIGNhdGVnb3JpY2FsIHZhbHVlcyAoaW4gdGhlIGNhc2Ugb2YgY2xhc3NpZmljYXRpb24pIG9mIHRoZSBvdXRjb21lIHZhcmlhYmxlIG9mIGludGVyZXN0LiBXZSBsZWFybmVkIHRoYXQgd2Ugc3BlY2lmeSB0aGUgbW9kZWwgYW5kIGl0cyBzcGVjaWZpY2F0aW9ucyB1c2luZyB0aGUgYHBhcm5zaXBgIHBhY2thZ2UgYW5kIHRoYXQgd2UgYWxzbyB1c2UgdGhpcyBwYWNrYWdlIHRvIGZpdCB0aGUgbW9kZWwgdXNpbmcgdGhlIGBmaXQoKWAgZnVuY3Rpb24uIFdlIGxlYXJuZWQgdGhhdCB3ZSBpZiBqdXN0IHVzZSBgcGFyc25pcGAgdG8gZml0IHRoZSBtb2RlbCwgdGhlbiB3ZSBuZWVkIHRvIHVzZSB0aGUgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIChvdXRwdXQgZnJvbSBganVpY2UoKWApLiBXZSBsZWFybmVkIHRoYXQgd2UgY2FuIHVzZSB0aGUgcmF3IHRyYWluaW5nIGRhdGEgaWYgd2UgdXNlIHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlIHRvIGNyZWF0ZSBhIHdvcmtmbG93IHRoYXQgcHJlLXByb2Nlc3NlcyBvdXIgZGF0YSBmb3IgdXMuICAgCgpXZSBsZWFybmVkIHRoYXQgaWYgdGhlIG1vZGVsIGZpdHMgd2VsbCB0aGFuIHRoZSBlc3RpbWF0ZWQgdmFsdWVzIHdpbGwgYmUgdmVyeSBzaW1pbGFyIHRvIHRoZSB0cnVlIG91dGNvbWUgdmFyaWFibGUgdmFsdWVzIGluIG91ciB0cmFpbmluZyBkYXRhLiBXZSBsZWFybmVkIHRoYXQgd2UgY2FuIGFzc2VzcyBtb2RlbCBwZXJmb3JtYW5jZSB1c2luZyB0aGUgYHlhcmRzdGlja2AgcGFja2FnZSB3aXRoIHRoZSBgbWV0cmljc2AgZnVuY3RpbyBvciB0aGUgYHR1bmVgIHBhY2thZ2UgYW5kIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIChyZXF1aXJlZCBpZiB1c2luZyBjcm9zcyB2YWxpZGF0aW9uIG9yIHR1bmluZykuIFdlIGFsc28gbGVhcm5lZCB0aGF0IHdlIGNhbiB1c2Ugc3Vic2V0cyBvZiBvdXIgdHJhaW5pbmcgZGF0YSAod2hpY2ggd2UgY3JlYXRlZCB3aXRoIHRoZSBgcnNhbXBsZWAgcGFja2FnZSkgdG8gcGVyZm9ybSBjcm9zcyB2YWxpZGF0aW9uIHRvIGdldCBhIGJldHRlciBlc3RpbWF0ZSBhYm91dCB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIG1vZGVsIHVzaW5nIG91ciB0cmFpbmluZyBkYXRhLCBhcyB3ZSB3YW50IG91ciByZXN1bHRzIHRvIGJlIGdlbmVyYWxpemFibGUgYW5kIHRvIHBlcmZvcm0gd2VsbCB3aXRoIG90aGVyIGRhdGEsIG5vdCBqdXN0IG91ciB0cmFpbmluZyBkYXRhLiBXZSB1c2VkIHRoZSBgZml0X3Jlc2FtcGxlcygpYCBmdW5jdGlvbiBvZiB0aGUgdHVuZSBwYWNrYWdlIHRvIGZpdCBvdXIgbW9kZWwgb24gb3VyIGRpZmZlcmVudCB0cmFpbmluZyBkYXRhIHN1YnNldHMgYW5kIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIChhbHNvIG9mIHRoZSBgdHVuZWAgcGFja2FnZSkgdG8gZXZhbHVhdGUgbW9kZWwgcGVyZm9ybWFuY2UgdXNpbmcgdGhlc2Ugc3Vic2V0cy4gIFdlIGFsc28gbGVhcm5lZCB0aGF0IHdlIGNhbiBwb3RlbnRpYWxseSBpbXByb3ZlIG1vZGVsIHBlcmZvcm1hbmNlIGJ5IHR1bmluZyBhc3BlY3RzIGFib3V0IHRoZSBtb2RlbCBjYWxsZWQgW2h5cGVycGFyYW1ldGVyc10oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9kaWZmZXJlbmNlLWJldHdlZW4tYS1wYXJhbWV0ZXItYW5kLWEtaHlwZXJwYXJhbWV0ZXIvKXt0YXJnZXQ9Il9ibGFuayJ9IHRvIGRldGVybWluZSB0aGUgYmVzdCBvcHRpb24gZm9yIG1vZGVsIHBlcmZvcm1hbmNlLiBXZSBsZWFybmVkIHRoYXQgd2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlIGB0dW5lYCBhbmQgYGRpYWxzYCBwYWNrYWdlcyBhbmQgZXZhbHVhdGluZyB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIG1vZGVsIHdpdGggdGhlIGRpZmZlcmVudCBoeXBlcnBhcmFtZXRlciBvcHRpb25zIGFuZCBvdXIgdHJhaW5pbmcgZGF0YSBzdWJzZXRzIHRoYXQgd2UgdXNlZCBmb3IgY3Jvc3MgdmFsaWRhdGlvbi4gQWZ0ZXIgd2UgdGVzdGVkIHNldmVyYWwgZGlmZmVyZW50IG1ldGhvZHMgdG8gbW9kZWwgb3VyIGRhdGEsIHdlIGNvbXBhcmVkIHRoZW0gdG8gY2hvb3NlIHRoZSBiZXN0IHBlcmZvcm1pbmcgbW9kZWwgYXMgb3VyIGZpbmFsIG1vZGVsLiAgCgoKNS4gT3ZlcmFsbCBtb2RlbCBwZXJmb3JtYW5jZSBldmFsdWF0aW9uICAKCk9uY2Ugd2UgY2hvc2Ugb3VyIGZpbmFsIG1vZGVsLCB3ZSBldmFsdWF0ZWQgdGhlIGZpbmFsIG1vZGVsIHBlcmZvcm1hbmNlIHVzaW5nIHRoZSB0ZXN0aW5nIGRhdGEgdXNpbmcgdGhlIGBsYXN0X2ZpdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UuIFRoaXMgZ2l2ZXMgdXMgYSBiZXR0ZXIgZXN0aW1hdGUgYWJvdXQgaG93IHdlbGwgdGhlIG1vZGVsIHdpbGwgcHJlZGljdCBvciBjbGFzc2lmeSB0aGUgb3V0Y29tZSB2YXJpYWJsZSBvZiBpbnRlcmVzdCB3aXRoIG5ldyBpbmRlcGVuZGVudCBkYXRhLiBJZGVhbGx5IG9uZSB3b3VsZCBhbHNvIHBlcmZvcm0gYW4gZXZhbHVhdGlvbiB3aXRoIGluZGVwZW5kZW50IGRhdGEgdG8gcHJvdmlkZSBhIHNlbnNlIG9mIGhvdyBnZW5lcmFsaXphYmxlIHRoZSBtb2RlbCBpcyB0byBvdGhlciBkYXRhIHNvdXJjZXMuIAoKV2UgYWxzbyBzYXcgdGhhdCB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9wcmVkaWN0aW9ucygpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UgdG8gZ2V0IHRoZSBwcmVkaWN0aW9ucyBmb3Igb3VyIHRlc3QgZGF0YS4gV2Ugc2F3IHRoYXQgd2UgY2FuIGdldCBtb3JlIGRldGFpbGVkIHByZWRpY3Rpb24gZGF0YSB1c2luZyB0aGUgYHByZWRpY3QoKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlLgoKPC9kZXRhaWxzPgoKCgojIyBTdWdnZXN0ZWQgSG9tZXdvcmsKClN0dWRlbnRzIGNhbiBwcmVkaWN0IGFpciBwb2xsdXRpb24gbW9uaXRvciB2YWx1ZXMgdXNpbmcgYSBkaWZmZXJlbnQgYWxnb3JpdGhtIGFuZCBwcm92aWRlIGFuIGV4cGxhbmF0aW9uIGZvciBob3cgdGhhdCBhbGdvcml0aG0gd29ya3MgYW5kIHdoeSBpdCBtYXkgYmUgYSBnb29kIGNob2ljZSBmb3IgbW9kZWxpbmcgdGhpcyBkYXRhLgoKCiMgKipBZGRpdGlvbmFsIEluZm9ybWF0aW9uKioKKioqCgojIyBIZWxwZnVsIExpbmtzCgoxLiBBIHJldmlldyBvZiBbdGlkeW1vZGVsc10oaHR0cHM6Ly9ydmlld3MucnN0dWRpby5jb20vMjAxOS8wNi8xOS9hLWdlbnRsZS1pbnRyby10by10aWR5bW9kZWxzLyl7dGFyZ2V0PSJfYmxhbmsifSAgCjIuIEEgW2NvdXJzZSBvbiB0aWR5bW9kZWxzXShodHRwczovL2p1bGlhc2lsZ2UuY29tL2Jsb2cvdGlkeW1vZGVscy1tbC1jb3Vyc2UvKXt0YXJnZXQ9Il9ibGFuayJ9IGJ5IEp1bGlhIFNpbGdlICAKMy4gW01vcmUgZXhhbXBsZXMsIGV4cGxhbmF0aW9ucywgYW5kIGluZm8gYWJvdXQgdGlkeW1vZGVscyBkZXZlbG9wbWVudF0oaHR0cHM6Ly93d3cudGlkeW1vZGVscy5vcmcvbGVhcm4vKXt0YXJnZXQ9Il9ibGFuayJ9IGZyb20gdGhlIGRldmVsb3BlcnMgIAo0LiBBIGd1aWRlIGZvciBbcHJlLXByb2Nlc3Npbmcgd2l0aCByZWNpcGVzXShodHRwOi8vd3d3LnJlYmVjY2FiYXJ0ZXIuY29tL2Jsb2cvMjAxOS0wNi0wNl9wcmVfcHJvY2Vzc2luZy8pe3RhcmdldD0iX2JsYW5rIn0gIAo1LiBBIFtndWlkZV0oaHR0cHM6Ly9icmlhdHRlLmdpdGh1Yi5pby9nZ2NvcnIvKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciB1c2luZyBHR2FsbHkgdG8gY3JlYXRlIGNvcnJlbGF0aW9uIHBsb3RzICAKNi4gQSBbZ3VpZGVdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE4LzExL3BhcnNuaXAtMC0wLTEvKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciB1c2luZyBwYXJzbmlwIHRvIHRyeSBkaWZmZXJlbnQgYWxnb3JpdGhtcyBvciBlbmdpbmVzICAKNy4gQSBbbGlzdCBvZiByZWNpcGUgZnVuY3Rpb25zXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvcmVmZXJlbmNlL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIAo4LiBBIGdyZWF0IGJsb2cgcG9zdCBhYm91dCBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3RyYWluLXRlc3Qtc3BsaXQtYW5kLWNyb3NzLXZhbGlkYXRpb24taW4tcHl0aG9uLTgwYjYxYmVjYTRiNil7dGFyZ2V0PSJfYmxhbmsifSAgCjkuIEEgZGlzY3Vzc2lvbiBhYm91dCBbZXZhbHVhdGluZyBtb2RlbCBwZXJmb3JtYW5jZV0oaHR0cHM6Ly9tZWRpdW0uY29tL0BsaW1hdmFsbGFudGluL21ldHJpY3MtdG8tbWVhc3VyZS1tYWNoaW5lLWxlYXJuaW5nLW1vZGVsLXBlcmZvcm1hbmNlLWU4Yzk2MzY2NTQ3Nil7dGFyZ2V0PSJfYmxhbmsifSBmb3IgYSBkZWVwZXIgZXhwbGFuYXRpb24gYWJvdXQgaG93IHRvIGV2YWx1YXRlIG1vZGVsIHBlcmZvcm1hbmNlICAKMTAuIFtSU3R1ZGlvIGNoZWF0c2hlZXRzXShodHRwczovL3JzdHVkaW8uY29tL3Jlc291cmNlcy9jaGVhdHNoZWV0cy8pe3RhcmdldD0iX2JsYW5rIn0KMTEuIEFuIFtleHBsYW5hdGlvbl0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3N1cGVydmlzZWQtdnMtdW5zdXBlcnZpc2VkLWxlYXJuaW5nLTE0ZjY4ZTMyZWE4ZCl7dGFyZ2V0PSJfYmxhbmsifSBvZiBzdXBlcnZpc2VkIHZzIHVuc3VwZXJ2aXNlZCBtYWNoaW5lIGxlYXJuaW5nIGFuZCBiaWFzLXZhcmlhbmNlIHRyYWRlLW9mZi4KMTIuIEEgdGhvcm91Z2ggW2V4cGxhbmF0aW9uXShodHRwczovL3JveWFsc29jaWV0eXB1Ymxpc2hpbmcub3JnL2RvaS8xMC4xMDk4L3JzdGEuMjAxNS4wMjAyIzp+OnRleHQ9UHJpbmNpcGFsJTIwY29tcG9uZW50JTIwYW5hbHlzaXMlMjAoUENBKSUyMGlzLHZhcmlhYmxlcyUyMHRoYXQlMjBzdWNjZXNzaXZlbHklMjBtYXhpbWl6ZSUyMHZhcmlhbmNlLil7dGFyZ2V0PSJfYmxhbmsifSBvZiBwcmluY2lwYWwgY29tcG9uZW50IGFuYWx5c2lzLgoxMy4gSWYgeW91IGhhdmUgYWNjZXNzLCB0aGlzIGlzIGEgZ3JlYXQgW2Rpc2N1c3Npb25dKGh0dHBzOi8vd3d3LnRhbmRmb25saW5lLmNvbS9kb2kvYWJzLzEwLjEwODAvMDAwMzEzMDUuMTk4NC4xMDQ4MzE4Myl7dGFyZ2V0PSJfYmxhbmsifSAgYWJvdXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBpbmRlcGVuZGVuY2UsIG9ydGhvZ29uYWxpdHksIGFuZCBsYWNrIG9mIGNvcnJlbGF0aW9uLgoxNC4gR3JlYXQgW3ZpZGVvIGV4cGxhbmF0aW9uXShodHRwczovL3lvdXR1LmJlL19VVkhuZUJVQlcwKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIFBDQS4gIAoKPHU+VGVybXMgYW5kIGNvbmNlcHRzIGNvdmVyZWQ6PC91PiAgCgpbVGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltJbXB1dGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JbXB1dGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAgCltUcmFuc2Zvcm1hdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGF0YV90cmFuc2Zvcm1hdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gIApbRGlzY3JldGl6YXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Rpc2NyZXRpemF0aW9uX29mX2NvbnRpbnVvdXNfZmVhdHVyZXMpe3RhcmdldD0iX2JsYW5rIn0gIApbRHVtbXkgVmFyaWFibGVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EdW1teV92YXJpYWJsZV8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gIApbT25lIEhvdCBFbmNvZGluZ10oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS93aHktb25lLWhvdC1lbmNvZGUtZGF0YS1pbi1tYWNoaW5lLWxlYXJuaW5nLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltEYXRhIFR5cGUgQ29udmVyc2lvbnNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9oYWJsYXIvdmlnbmV0dGVzL2NvbnZlcnQuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgCltJbnRlcmFjdGlvbl0oaHR0cHM6Ly9zdGF0aXN0aWNzYnlqaW0uY29tL3JlZ3Jlc3Npb24vaW50ZXJhY3Rpb24tZWZmZWN0cy8pe3RhcmdldD0iX2JsYW5rIn0gIApbTm9ybWFsaXphdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTm9ybWFsaXphdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gIApbRGltZW5zaW9uYWxpdHkgUmVkdWN0aW9uL1NpZ25hbCBFeHRyYWN0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaW1lbnNpb25hbGl0eV9yZWR1Y3Rpb24pe3RhcmdldD0iX2JsYW5rIn0gIApbUm93IE9wZXJhdGlvbnNdKGh0dHBzOi8vdGFydGFydXMub3JnL2dhcmV0aC9tYXRocy9MaW5lYXJfQWxnZWJyYS9yb3dfb3BlcmF0aW9ucy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gIApbTmVhciBaZXJvIFZhcmFpbmNlXShodHRwczovL3d3dy5yLWJsb2dnZXJzLmNvbS9uZWFyLXplcm8tdmFyaWFuY2UtcHJlZGljdG9ycy1zaG91bGQtd2UtcmVtb3ZlLXRoZW0vKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1BhcmFtZXRlcnMgYW5kIEh5cGVycGFyYW1ldGVyc10oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9kaWZmZXJlbmNlLWJldHdlZW4tYS1wYXJhbWV0ZXItYW5kLWEtaHlwZXJwYXJhbWV0ZXIvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgCltTdXBlcnZpc2VkIGFuZCBVbnNwZXJ2aXNlZCBMZWFybmluZ10oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3N1cGVydmlzZWQtdnMtdW5zdXBlcnZpc2VkLWxlYXJuaW5nLTE0ZjY4ZTMyZWE4ZCl7dGFyZ2V0PSJfYmxhbmsifSAgCltQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzXShodHRwczovL21lZGl1bS5jb20vQHNhdmFzdGFtaXJrby9wY2EtYS1saW5lYXItdHJhbnNmb3JtYXRpb24tZjhhYWNkNGViMDA3KXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0xpbmVhciBDb21iaW5hdGlvbnNdKGh0dHBzOi8vd3d3Lm1hdGhib290Y2FtcHMuY29tL2xpbmVhci1jb21iaW5hdGlvbnMtdmVjdG9ycy8pe3RhcmdldD0iX2JsYW5rIn0gIApbRGVjaXNpb24gVHJlZV0oaHR0cHM6Ly9tZWRpdW0uY29tL2dyZXlhdG9tL2RlY2lzaW9uLXRyZWVzLWEtc2ltcGxlLXdheS10by12aXN1YWxpemUtYS1kZWNpc2lvbi1kYzUwNmE0MDNhZWIpe3RhcmdldD0iX2JsYW5rIn0gIApbUmFuZG9tIEZvcmVzdF0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL2RlY2lzaW9uLXRyZWUtZW5zZW1ibGVzLWJhZ2dpbmctYW5kLWJvb3N0aW5nLTI2NmE4YmE2MGZkOSl7dGFyZ2V0PSJfYmxhbmsifSAgCgoKIDx1PioqUGFja2FnZXMgdXNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHk6KiogPC91PgoKUGFja2FnZSAgIHwgVXNlIGluIHRoaXMgY2FzZSBzdHVkeSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YQpbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCB0aGUgQ1NWIGZpbGUgZGF0YQpbZHBseXJdKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHZpZXcvYXJyYW5nZS9maWx0ZXIvc2VsZWN0L2NvbXBhcmUgc3BlY2lmaWMgc3Vic2V0cyBvZiB0aGUgZGF0YSAKW3NraW1yXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEKW3N1bW1hcnl0b29sc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhIGluIGEgZGlmZmVyZW50IHN0eWxlClttYWdyaXR0cl0oaHR0cHM6Ly9tYWdyaXR0ci50aWR5dmVyc2Uub3JnL2FydGljbGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHVzZSB0aGUgYCU8PiVgIHBpcHBpbmcgb3BlcmF0b3IgCltjb3JycGxvdF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2NvcnJwbG90L3ZpZ25ldHRlcy9jb3JycGxvdC1pbnRyby5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbWFrZSBsYXJnZSBjb3JyZWxhdGlvbiBwbG90cwpbR0dhbGx5XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvR0dhbGx5L0dHYWxseS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBtYWtlIHNtYWxsZXIgY29ycmVsYXRpb24gcGxvdHMgIApbcnNhbXBsZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yc2FtcGxlL2FydGljbGVzL0Jhc2ljcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldHMgYW5kIHRvIHNwbGl0IHRoZSB0cmFpbmluZyBzZXQgZm9yIGNyb3NzLXZhbGlkYXRpb24gIApbcmVjaXBlc10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gcHJlLXByb2Nlc3MgZGF0YSBmb3IgbW9kZWxpbmcgaW4gYSB0aWR5IGFuZCByZXByb2R1Y2libGUgd2F5IGFuZCB0byBleHRyYWN0IHByZS1wcm9jZXNzZWQgZGF0YSAobWFqb3IgZnVuY3Rpb25zIGFyZSBgcmVjaXBlKClgICwgYHByZXAoKWAgYW5kIHZhcmlvdXMgdHJhbnNmb3JtYXRpb24gYHN0ZXBfKigpYCBmdW5jdGlvbnMsIGFzIHdlbGwgYXMgYGp1aWNlKClgIC0gZXh0cmFjdHMgZmluYWwgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIGFuZCBgYmFrZSgpYCAtIGFwcGxpZXMgcmVjaXBlIHN0ZXBzIHRvIHRlc3RpbmcgZGF0YSkuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JlY2lwZXMvcmVjaXBlcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gIGZvciBtb3JlIGluZm8uCltwYXJzbmlwXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3BhcnNuaXAvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCBhbiBpbnRlcmZhY2UgdG8gY3JlYXRlIG1vZGVscyAobWFqb3IgZnVuY3Rpb25zIGFyZSAgYGZpdCgpYCwgYHNldF9lbmdpbmUoKWApClt5YXJkc3RpY2tdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8veWFyZHN0aWNrLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG1vZGVscwpbYnJvb21dKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE4LzA3L2Jyb29tLTAtNS0wLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGdldCB0aWR5IG91dHB1dCBmb3Igb3VyIG1vZGVsIGZpdCBhbmQgcGVyZm9ybWFuY2UKW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1ha2UgdmlzdWFsaXphdGlvbnMgd2l0aCBtdWx0aXBsZSBsYXllcnMKW2RpYWxzXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOS8xMC9kaWFscy0wLTAtMy8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBzcGVjaWZ5IGh5cGVyLXBhcmFtZXRlciB0dW5pbmcKW3R1bmVdKGh0dHBzOi8vdHVuZS50aWR5bW9kZWxzLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIGNyb3NzIHZhbGlkYXRpb24sIHR1bmUgaHlwZXItcGFyYW1ldGVycywgYW5kIGdldCBwZXJmb3JtYW5jZSBtZXRyaWNzClt3b3JrZmxvd3NdKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy93b3JrZmxvd3MvdmVyc2lvbnMvMC4xLjEpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgbW9kZWxpbmcgd29ya2Zsb3cgdG8gc3RyZWFtbGluZSB0aGUgbW9kZWxpbmcgcHJvY2VzcwpbdmlwXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdmlwL3ZpcC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgdmFyaWFibGUgaW1wb3J0YW5jZSBwbG90cwpbcmFuZG9tRm9yZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIHRoZSByYW5kb20gZm9yZXN0IGFuYWx5c2lzCltkb1BhcmFsbGVsXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZG9QYXJhbGxlbC9kb1BhcmFsbGVsLnBkZikgfCB0byBmaXQgY3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGVzIGluIHBhcmFsbGVsIApbc3RyaW5ncl0oaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvc3RyaW5nci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFuaXB1bGF0ZSB0aGUgdGV4dCB0aGUgbWFwIGRhdGEKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzZXBhcmF0ZSBkYXRhIHdpdGhpbiBhIGNvbHVtbiBpbnRvIG11bHRpcGxlIGNvbHVtbnMKW3JuYXR1cmFsZWFydGhdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ybmF0dXJhbGVhcnRoL1JFQURNRS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IHRoZSBnZW9tZXRyeSBkYXRhIGZvciB0aGUgZWFydGggdG8gcGxvdCB0aGUgVVMKW21hcHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYXBzL21hcHMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IG1hcCBkYXRhYmFzZSBkYXRhIGFib3V0IGNvdW50aWVzIHRvIGRyYXcgdGhlbSBvbiBvdXIgVVMgbWFwCltzZl0oaHR0cHM6Ly9yLXNwYXRpYWwuZ2l0aHViLmlvL3NmLyl7dGFyZ2V0PSJfYmxhbmsifSAgfCB0byBjb252ZXJ0IHRoZSBtYXAgZGF0YSBpbnRvIGEgZGF0YSBmcmFtZQpbbHdnZW9tXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbHdnZW9tL2x3Z2VvbS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byB1c2UgdGhlIGBzZmAgZnVuY3Rpb24gdG8gY29udmVydCB0aGUgbWFwIGdlb2dyYXBoaWNhbCBkYXRhCltyZ2Vvc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JnZW9zL3JnZW9zLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHVzZSBnZW9tZXRyeSBkYXRhCltwYXRjaHdvcmtdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9wYXRjaHdvcmsvcGF0Y2h3b3JrLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGFsbG93IHBsb3RzIHRvIGJlIGNvbWJpbmVkCgoKIyMgU2Vzc2lvbiBpbmZvIAoKCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAoKCiMjIEFja25vd2xlZGdlbWVudHMKCgpXZSB3b3VsZCBsaWtlIHRvIGFja25vd2xlZGdlIFtSb2dlciBQZW5nXShodHRwOi8vd3d3LmJpb3N0YXQuamhzcGguZWR1L35ycGVuZy8pLCBbTWVnYW4gTGF0c2hhd10oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMTcwOC9tZWdhbi13ZWlsLWxhdHNoYXcpLCBhbmQgW0tpcnN0ZW4gS29laGxlcl0oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMjkyOC9raXJzdGVuLWtvZWhsZXIpIGZvciBhc3Npc3RpbmcgaW4gZnJhbWluZyB0aGUgbWFqb3IgZGlyZWN0aW9uIG9mIHRoZSBjYXNlIHN0dWR5LgoKV2Ugd291bGQgYWxzbyBsaWtlIHRvIGFja25vd2xlZGdlIHRoZSBbQmxvb21iZXJnIEFtZXJpY2FuIEhlYWx0aCBJbml0aWF0aXZlXShodHRwczovL2FtZXJpY2FuaGVhbHRoLmpodS5lZHUvKSBmb3IgZnVuZGluZyB0aGlzIHdvcmsuIAo=